From 59b0077565bc056283dad048a237dbc183000c76 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 1 Dec 2016 22:31:56 +0100 Subject: [PATCH] WIP compiles and doesn't crash (much) but tests are failing --- CHANGELOG.md | 3 + clippy_lints/src/attrs.rs | 8 +- clippy_lints/src/bit_mask.rs | 19 ++-- clippy_lints/src/blacklisted_name.rs | 2 +- clippy_lints/src/consts.rs | 33 +++---- clippy_lints/src/copies.rs | 2 +- clippy_lints/src/derive.rs | 6 +- clippy_lints/src/drop_ref.rs | 4 +- clippy_lints/src/enum_glob_use.rs | 24 +---- clippy_lints/src/eta_reduction.rs | 4 +- clippy_lints/src/eval_order_dependence.rs | 50 +++++----- clippy_lints/src/format.rs | 10 +- clippy_lints/src/functions.rs | 11 ++- .../src/if_let_redundant_pattern_matching.rs | 2 +- clippy_lints/src/let_if_seq.rs | 21 ++--- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/lifetimes.rs | 14 +-- clippy_lints/src/loops.rs | 92 ++++++++++--------- clippy_lints/src/map_clone.rs | 6 +- clippy_lints/src/matches.rs | 4 +- clippy_lints/src/mem_forget.rs | 4 +- clippy_lints/src/methods.rs | 8 +- clippy_lints/src/minmax.rs | 4 +- clippy_lints/src/misc.rs | 42 +++++---- clippy_lints/src/mut_reference.rs | 2 +- clippy_lints/src/needless_borrow.rs | 2 +- clippy_lints/src/no_effect.rs | 37 +++++--- clippy_lints/src/ok_if_let.rs | 2 +- .../src/overflow_check_conditional.rs | 12 +-- clippy_lints/src/panic.rs | 5 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/print.rs | 17 ++-- clippy_lints/src/ptr.rs | 4 +- clippy_lints/src/ranges.rs | 18 ++-- clippy_lints/src/regex.rs | 4 +- clippy_lints/src/serde.rs | 2 +- clippy_lints/src/shadow.rs | 18 ++-- clippy_lints/src/swap.rs | 4 +- clippy_lints/src/transmute.rs | 9 +- clippy_lints/src/types.rs | 28 +++--- clippy_lints/src/unsafe_removed_from_name.rs | 17 ++-- clippy_lints/src/unused_label.rs | 2 +- clippy_lints/src/utils/higher.rs | 23 +---- clippy_lints/src/utils/hir.rs | 69 +++++++++----- clippy_lints/src/utils/inspector.rs | 32 ++++--- clippy_lints/src/utils/internal_lints.rs | 4 +- clippy_lints/src/utils/mod.rs | 46 ++++++++-- 47 files changed, 387 insertions(+), 347 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c08d567ec52..9f798c31af1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.104 — 2016-12-01 +* Update to *rustc 1.15.0-nightly (1c448574b 2016-11-28)* + ## 0.0.103 — 2016-11-25 * Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)* diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index f03dcbc5a9a..0d5e5a4cde6 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -105,7 +105,7 @@ impl LateLintPass for AttrPass { } 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() { @@ -113,7 +113,7 @@ impl LateLintPass for AttrPass { // 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; } } @@ -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 diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index b021079fd97..8a4664d62b7 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -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; @@ -245,18 +245,13 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { 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, } diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index 55d0efd3536..ce7adda092c 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -39,7 +39,7 @@ 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 { + if let PatKind::Binding(_, _, ref ident, _) = pat.node { if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) { span_lint(cx, BLACKLISTED_NAME, diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 89c57bba233..afbf9666b10 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -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 { 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 { + fn fetch_path(&mut self, qpath: &QPath, id: NodeId) -> Option { 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 diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index b46fda3d2f2..726b8f214fa 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -254,7 +254,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap { + 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)); } diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 59687aa191b..35ea620c128 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -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. @@ -89,7 +89,7 @@ impl LateLintPass for Derive { fn check_hash_peq<'a, 'tcx: 'a>(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); diff --git a/clippy_lints/src/drop_ref.rs b/clippy_lints/src/drop_ref.rs index b369a3ae386..dc240a0df7d 100644 --- a/clippy_lints/src/drop_ref.rs +++ b/clippy_lints/src/drop_ref.rs @@ -38,8 +38,8 @@ impl LintPass for Pass { impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &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; diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 4641bb05431..f4f8d6f378b 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -2,8 +2,7 @@ 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; @@ -48,24 +47,9 @@ 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 { + if let Def::Enum(_) = path.def { + span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); } } } diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index ee0767f57df..d915755fbd1 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -72,9 +72,9 @@ fn check_closure(cx: &LateContext, expr: &Expr) { _ => (), } 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; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index d3c06a58179..5998f415129 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -61,16 +61,18 @@ impl LateLintPass for EvalOrderDependence { // 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); + } } } } @@ -293,19 +295,21 @@ impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> { } 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" + ); + } } } } diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 5a2c5f5c852..92970bc5e01 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -45,10 +45,9 @@ impl LateLintPass for Pass { // `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])); diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index c6f17b615b6..82f210f3d50 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -138,9 +138,9 @@ impl Functions { } } -fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option { - 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 { + if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) { + Some(def_id) } else { None } @@ -183,8 +183,9 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> { 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, diff --git a/clippy_lints/src/if_let_redundant_pattern_matching.rs b/clippy_lints/src/if_let_redundant_pattern_matching.rs index 25ff7244cf1..878a1b7313b 100644 --- a/clippy_lints/src/if_let_redundant_pattern_matching.rs +++ b/clippy_lints/src/if_let_redundant_pattern_matching.rs @@ -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()" } diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index 598f1b3a57a..e1f20eb1859 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -65,19 +65,18 @@ impl LateLintPass for LetIfSeq { 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) @@ -137,9 +136,8 @@ struct UsedVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'v 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; @@ -154,9 +152,8 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir:: 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, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a90f121fe79..7e2b85df572 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -256,7 +256,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); diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 710604b3a28..236919bfc25 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -239,12 +239,12 @@ 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 { - 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 { + fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) { + if let QPath::Resolved(_, ref path) = *qpath { + let last_path_segment = path.segments.last().map(|s| &s.parameters); + if let Some(&AngleBracketedParameters(ref params)) = last_path_segment { + if params.lifetimes.is_empty() { + 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); @@ -277,7 +277,7 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> { TyRptr(None, _) => { self.record(&None); } - TyPath(_, ref path) => { + TyPath(ref path) => { self.collect_anonymous_lifetimes(path, ty); } _ => (), diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f5d9b91bb8c..d752e78cddf 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -366,26 +366,28 @@ impl LateLintPass for Pass { } if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node { let pat = &arms[0].pats[0].node; - if let (&PatKind::TupleStruct(ref path, ref pat_args, _), + if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _), &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { let iter_expr = &method_args[0]; - if let Some(lhs_constructor) = path.segments.last() { - if &*method_name.node.as_str() == "next" && - match_trait_method(cx, match_expr, &paths::ITERATOR) && - &*lhs_constructor.name.as_str() == "Some" && - !is_refutable(cx, &pat_args[0]) && - !is_iterator_used_after_while_let(cx, iter_expr) { - let iterator = snippet(cx, method_args[0].span, "_"); - let loop_var = snippet(cx, pat_args[0].span, "_"); - span_lint_and_then(cx, - WHILE_LET_ON_ITERATOR, - expr.span, - "this loop could be written as a `for` loop", - |db| { - db.span_suggestion(expr.span, - "try", - format!("for {} in {} {{ .. }}", loop_var, iterator)); - }); + if let QPath::Resolved(_, ref path) = *qpath { + if let Some(lhs_constructor) = path.segments.last() { + if &*method_name.node.as_str() == "next" && + match_trait_method(cx, match_expr, &paths::ITERATOR) && + &*lhs_constructor.name.as_str() == "Some" && + !is_refutable(cx, &pat_args[0]) && + !is_iterator_used_after_while_let(cx, iter_expr) { + let iterator = snippet(cx, method_args[0].span, "_"); + let loop_var = snippet(cx, pat_args[0].span, "_"); + span_lint_and_then(cx, + WHILE_LET_ON_ITERATOR, + expr.span, + "this loop could be written as a `for` loop", + |db| { + db.span_suggestion(expr.span, + "try", + format!("for {} in {} {{ .. }}", loop_var, iterator)); + }); + } } } } @@ -421,10 +423,10 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) { if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) { // the var must be a single name - if let PatKind::Binding(_, ref ident, _) = pat.node { + if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { let mut visitor = VarVisitor { cx: cx, - var: cx.tcx.expect_def(pat.id).def_id(), + var: def_id, indexed: HashMap::new(), nonindex: false, }; @@ -510,7 +512,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool { let ExprMethodCall(method, _, ref len_args) = expr.node, len_args.len() == 1, &*method.node.as_str() == "len", - let ExprPath(_, ref path) = len_args[0].node, + let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node, path.segments.len() == 1, &path.segments[0].name == var ], { @@ -732,7 +734,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool { match *pat { PatKind::Wild => true, - PatKind::Binding(_, ident, None) if ident.node.as_str().starts_with('_') => { + PatKind::Binding(_, _, ident, None) if ident.node.as_str().starts_with('_') => { let mut visitor = UsedVisitor { var: ident.node, used: false, @@ -751,7 +753,7 @@ struct UsedVisitor { impl<'a> Visitor<'a> for UsedVisitor { fn visit_expr(&mut self, expr: &Expr) { - if let ExprPath(None, ref path) = expr.node { + if let ExprPath(QPath::Resolved(None, ref path)) = expr.node { if path.segments.len() == 1 && path.segments[0].name == self.var { self.used = true; return; @@ -771,20 +773,21 @@ struct VarVisitor<'v, 't: 'v> { impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { fn visit_expr(&mut self, expr: &'v Expr) { - if let ExprPath(None, ref path) = expr.node { - if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var { - // we are referencing our variable! now check if it's as an index - if_let_chain! {[ - let Some(parexpr) = get_parent_expr(self.cx, expr), - let ExprIndex(ref seqexpr, _) = parexpr.node, - let ExprPath(None, ref seqvar) = seqexpr.node, - seqvar.segments.len() == 1 - ], { - let def_map = self.cx.tcx.def_map.borrow(); - if let Some(def) = def_map.get(&seqexpr.id) { - match def.base_def { + if let ExprPath(ref qpath) = expr.node { + 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 { + // we are referencing our variable! now check if it's as an index + if_let_chain! {[ + let Some(parexpr) = get_parent_expr(self.cx, expr), + let ExprIndex(ref seqexpr, _) = parexpr.node, + let ExprPath(ref seqpath) = seqexpr.node, + let QPath::Resolved(None, ref seqvar) = *seqpath, + seqvar.segments.len() == 1 + ], { + let def = self.cx.tcx.tables().qpath_def(seqpath, seqexpr.id); + match def { Def::Local(..) | Def::Upvar(..) => { - let def_id = def.base_def.def_id(); + let def_id = def.def_id(); let node_id = self.cx.tcx.map.as_local_node_id(def_id).unwrap(); let extent = self.cx.tcx.region_maps.var_scope(node_id); @@ -797,11 +800,11 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> { } _ => (), } - } - }} - // we are not indexing anything, record that - self.nonindex = true; - return; + }} + // we are not indexing anything, record that + self.nonindex = true; + return; + } } } walk_expr(self, expr); @@ -1002,7 +1005,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { // Look for declarations of the variable if let DeclLocal(ref local) = decl.node { if local.pat.id == self.var_id { - if let PatKind::Binding(_, ref ident, _) = local.pat.node { + if let PatKind::Binding(_, _, ref ident, _) = local.pat.node { self.name = Some(ident.node); self.state = if let Some(ref init) = local.init { @@ -1071,8 +1074,9 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> { } fn var_def_id(cx: &LateContext, expr: &Expr) -> Option { - if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) { - if let Def::Local(def_id) = path_res.base_def { + if let ExprPath(ref qpath) = expr.node { + let path_res = cx.tcx.tables().qpath_def(qpath, expr.id); + if let Def::Local(def_id) = path_res { let node_id = cx.tcx.map.as_local_node_id(def_id).expect("That DefId should be valid"); return Some(node_id); } diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 07bbc703826..9d9b0a6e35b 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -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 { 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, } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 844715835b9..828e7eda026 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -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, }; diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 492962def6a..288c238474f 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -30,8 +30,8 @@ impl LintPass for MemForget { impl LateLintPass for MemForget { fn check_expr(&mut self, cx: &LateContext, e: &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]); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 53c6eae9188..1a824e467c4 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -701,7 +701,7 @@ 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 { + if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = fun.node { let path: &str = &path.segments .last() .expect("A path must have at least one segment") @@ -877,7 +877,7 @@ 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, + let hir::ExprPath(ref path) = fun.node, match_path(path, &paths::CSTRING_NEW), ], { span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span, @@ -1188,7 +1188,7 @@ 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, + let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = fun.node, path.segments.len() == 1 && &*path.segments[0].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 diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 771408a9be6..2b453f1c880 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -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) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 6ad63348920..854a8d144d6 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -173,7 +173,7 @@ impl LateLintPass for Pass { 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, @@ -186,7 +186,7 @@ impl LateLintPass for Pass { 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, ".."); @@ -220,10 +220,10 @@ impl LateLintPass for Pass { 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,19 +262,23 @@ 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(); - 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)) { - Some(binding) + ExprPath(ref qpath) => { + if let QPath::Resolved(_, ref path) = *qpath { + let binding = path.segments + .last() + .expect("path should always have at least one segment") + .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.tables().qpath_def(qpath, expr.id)) { + Some(binding) + } else { + None + } } else { None } @@ -299,7 +303,7 @@ impl LateLintPass for Pass { } fn check_pat(&mut self, cx: &LateContext, pat: &Pat) { - if let PatKind::Binding(_, ref ident, Some(ref right)) = pat.node { + if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node { if right.node == PatKind::Wild { span_lint(cx, REDUNDANT_PATTERN, @@ -366,7 +370,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 { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index b2cdb2cb49b..eadf0d8ce89 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -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()); } } diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index b2199c226e9..459b4faec5d 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -57,7 +57,7 @@ impl LateLintPass for NeedlessBorrow { 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 { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 973daa696b6..825aafb4be5 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -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) => { @@ -146,12 +150,17 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option { - 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) => { diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 1fdfe43b684..b7e7c70e41a 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -46,7 +46,7 @@ impl LateLintPass for Pass { 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.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; ], { diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index 98c2b986d20..06a1937e192 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -35,9 +35,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) = 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() diff --git a/clippy_lints/src/panic.rs b/clippy_lints/src/panic.rs index 97ad9173ef1..1d89c5ce507 100644 --- a/clippy_lints/src/panic.rs +++ b/clippy_lints/src/panic.rs @@ -39,9 +39,8 @@ impl LateLintPass for Pass { 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, diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index fdee5c256e1..8f25650bf58 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -40,7 +40,7 @@ impl LateLintPass for Pass { 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" { diff --git a/clippy_lints/src/print.rs b/clippy_lints/src/print.rs index 46d38a67a86..719d18bffeb 100644 --- a/clippy_lints/src/print.rs +++ b/clippy_lints/src/print.rs @@ -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 @@ -69,9 +69,9 @@ impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &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"]); } } } diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2863b14b112..f210ec4dbc0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -77,7 +77,7 @@ impl LateLintPass for PointerPass { check_fn(cx, &sig.decl, item.id); } } - + fn check_expr(&mut self, cx: &LateContext, expr: &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)) { @@ -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) } } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index ab02a62ad29..791843ee567 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -73,15 +73,19 @@ 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, + let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node, + let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node, iter_path == len_path ], { - span_lint(cx, - RANGE_ZIP_WITH_LEN, - expr.span, - &format!("It is more idiomatic to use {}.iter().enumerate()", - snippet(cx, iter_args[0].span, "_"))); + let Path { segments: ref iter_path, .. } = **iter_path; + let Path { segments: ref len_path, .. } = **len_path; + if iter_path == len_path { + span_lint(cx, + RANGE_ZIP_WITH_LEN, + expr.span, + &format!("It is more idiomatic to use {}.iter().enumerate()", + snippet(cx, iter_args[0].span, "_"))); + } }} } } diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index ec3013d36a1..11eaac0bbb9 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -115,10 +115,10 @@ impl LateLintPass for Pass { fn check_expr(&mut self, cx: &LateContext, expr: &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); diff --git a/clippy_lints/src/serde.rs b/clippy_lints/src/serde.rs index 6cf10d883d3..c5a23227555 100644 --- a/clippy_lints/src/serde.rs +++ b/clippy_lints/src/serde.rs @@ -29,7 +29,7 @@ impl LintPass for Serde { impl LateLintPass for Serde { fn check_item(&mut self, cx: &LateContext, item: &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; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index d23b1c9993f..c994d47d759 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,8 +1,8 @@ use reexport::*; use rustc::lint::*; -use rustc::hir::def::Def; use rustc::hir::*; use rustc::hir::intravisit::{Visitor, FnKind}; +use rustc::ty; use std::ops::Deref; use syntax::codemap::Span; use utils::{higher, in_external_macro, snippet, span_lint_and_then}; @@ -92,7 +92,7 @@ impl LateLintPass for Pass { fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) { let mut bindings = Vec::new(); for arg in &decl.inputs { - if let PatKind::Binding(_, ident, _) = arg.pat.node { + if let PatKind::Binding(_, _, ident, _) = arg.pat.node { bindings.push((ident.node, ident.span)) } } @@ -135,10 +135,10 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) { } } -fn is_binding(cx: &LateContext, pat: &Pat) -> bool { - match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) { - Some(Def::Variant(..)) | - Some(Def::Struct(..)) => false, +fn is_binding(cx: &LateContext, pat_id: NodeId) -> bool { + let var_ty = cx.tcx.tables().node_id_to_type(pat_id); + match var_ty.sty { + ty::TyAdt(..) => false, _ => true, } } @@ -146,9 +146,9 @@ fn is_binding(cx: &LateContext, pat: &Pat) -> bool { fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) { // TODO: match more stuff / destructuring match pat.node { - PatKind::Binding(_, ref ident, ref inner) => { + PatKind::Binding(_, _, ref ident, ref inner) => { let name = ident.node; - if is_binding(cx, pat) { + if is_binding(cx, pat.id) { let mut new_binding = true; for tup in bindings.iter_mut() { if tup.0 == name { @@ -344,7 +344,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e)) } ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner), - ExprPath(_, ref path) => path_eq_name(name, path), + ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path), _ => false, } } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 278df3bad35..bef66dd402e 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -65,7 +65,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { let StmtDecl(ref tmp, _) = w[0].node, let DeclLocal(ref tmp) = tmp.node, let Some(ref tmp_init) = tmp.init, - let PatKind::Binding(_, ref tmp_name, None) = tmp.pat.node, + let PatKind::Binding(_, _, ref tmp_name, None) = tmp.pat.node, // foo() = bar(); let StmtSemi(ref first, _) = w[1].node, @@ -74,7 +74,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) { // bar() = t; let StmtSemi(ref second, _) = w[2].node, let ExprAssign(ref lhs2, ref rhs2) = second.node, - let ExprPath(None, ref rhs2) = rhs2.node, + let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node, rhs2.segments.len() == 1, tmp_name.node.as_str() == rhs2.segments[0].name.as_str(), diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index a7e16a56f38..3a8680b1cf7 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -87,8 +87,8 @@ impl LintPass for Transmute { impl LateLintPass for Transmute { fn check_expr(&mut self, cx: &LateContext, e: &Expr) { if let ExprCall(ref path_expr, ref args) = e.node { - if let ExprPath(None, ref path) = 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::TRANSMUTE) { let from_ty = cx.tcx.tables().expr_ty(&args[0]); @@ -173,7 +173,7 @@ impl LateLintPass for Transmute { let arg = if from_pty.ty == to_rty.ty { arg } else { - arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, path, to_rty.ty))) + arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) }; db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); @@ -190,8 +190,9 @@ impl LateLintPass for Transmute { /// Get the snippet of `Bar` in `…::transmute`. If that snippet is not available , use /// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_` /// lifetime, but it should be rare. -fn get_type_snippet(cx: &LateContext, path: &Path, to_rty: ty::Ty) -> String { +fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: ty::Ty) -> String { if_let_chain!{[ + let QPath::Resolved(_, ref path) = *path, let Some(seg) = path.segments.last(), let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters, let Some(to_ty) = ang.types.get(1), diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index de8fbdcc5d7..008a1fbc6ce 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -7,7 +7,7 @@ use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, - span_help_and_lint, span_lint}; + span_help_and_lint, span_lint, opt_def_id}; use utils::paths; /// Handles all the linting of funky types @@ -74,17 +74,19 @@ impl LateLintPass for TypePass { if in_macro(cx, ast_ty.span) { return; } - if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) { - if let def::Def::Struct(..) = did.full_def() { - if Some(did.full_def().def_id()) == cx.tcx.lang_items.owned_box() { + if let TyPath(ref qpath) = ast_ty.node { + let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id); + if let Some(def_id) = opt_def_id(def) { + if def_id == cx.tcx.lang_items.owned_box().unwrap() { if_let_chain! {[ - let TyPath(_, ref path) = ast_ty.node, + let QPath::Resolved(_, ref path) = *qpath, let Some(ref last) = path.segments.last(), let PathParameters::AngleBracketedParameters(ref ag) = last.parameters, let Some(ref vec) = ag.types.get(0), - let Some(did) = cx.tcx.def_map.borrow().get(&vec.id), - let def::Def::Struct(..) = did.full_def(), - match_def_path(cx, did.full_def().def_id(), &paths::VEC), + let TyPath(ref qpath) = vec.node, + let def::Def::Struct(..) = cx.tcx.tables().qpath_def(qpath, vec.id), + let Some(did) = opt_def_id(cx.tcx.tables().qpath_def(qpath, vec.id)), + match_def_path(cx, did, &paths::VEC), ], { span_help_and_lint(cx, BOX_VEC, @@ -92,12 +94,12 @@ impl LateLintPass for TypePass { "you seem to be trying to use `Box>`. Consider using just `Vec`", "`Vec` is already on the heap, `Box>` makes an extra allocation."); }} - } else if match_def_path(cx, did.full_def().def_id(), &paths::LINKED_LIST) { + } else if match_def_path(cx, def_id, &paths::LINKED_LIST) { span_help_and_lint(cx, - LINKEDLIST, - ast_ty.span, - "I see you're using a LinkedList! Perhaps you meant some other data structure?", - "a VecDeque might work"); + LINKEDLIST, + ast_ty.span, + "I see you're using a LinkedList! Perhaps you meant some other data structure?", + "a VecDeque might work"); } } } diff --git a/clippy_lints/src/unsafe_removed_from_name.rs b/clippy_lints/src/unsafe_removed_from_name.rs index 7cd108dd02d..341848a868c 100644 --- a/clippy_lints/src/unsafe_removed_from_name.rs +++ b/clippy_lints/src/unsafe_removed_from_name.rs @@ -1,6 +1,5 @@ -use rustc::hir::*; use rustc::lint::*; -use syntax::ast::Name; +use syntax::ast::*; use syntax::codemap::Span; use syntax::symbol::InternedString; use utils::span_lint; @@ -34,16 +33,16 @@ impl LintPass for UnsafeNameRemoval { } } -impl LateLintPass for UnsafeNameRemoval { - fn check_item(&mut self, cx: &LateContext, item: &Item) { - if let ItemUse(ref item_use) = item.node { +impl EarlyLintPass for UnsafeNameRemoval { + fn check_item(&mut self, cx: &EarlyContext, item: &Item) { + if let ItemKind::Use(ref item_use) = item.node { match item_use.node { ViewPath_::ViewPathSimple(ref name, ref path) => { unsafe_to_safe_check( path.segments .last() .expect("use paths cannot be empty") - .name, + .identifier, *name, cx, &item.span ); @@ -62,9 +61,9 @@ impl LateLintPass for UnsafeNameRemoval { } } -fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: &Span) { - let old_str = old_name.as_str(); - let new_str = new_name.as_str(); +fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: &Span) { + let old_str = old_name.name.as_str(); + let new_str = new_name.name.as_str(); if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { span_lint(cx, UNSAFE_REMOVED_FROM_NAME, diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index e76b9b69708..73c87f36bba 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -66,7 +66,7 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor { match expr.node { hir::ExprBreak(Some(label), _) | hir::ExprAgain(Some(label)) => { - self.labels.remove(&label.node.as_str()); + self.labels.remove(&label.name.as_str()); } hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => { diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 26b45009a82..a2e8bc891b4 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -44,19 +44,6 @@ pub struct Range<'a> { /// Higher a `hir` range to something similar to `ast::ExprKind::Range`. pub fn range(expr: &hir::Expr) -> Option { - /// Skip unstable blocks. To be removed when ranges get stable. - fn unwrap_unstable(expr: &hir::Expr) -> &hir::Expr { - if let hir::ExprBlock(ref block) = expr.node { - if block.rules == hir::BlockCheckMode::PushUnstableBlock || block.rules == hir::BlockCheckMode::PopUnstableBlock { - if let Some(ref expr) = block.expr { - return expr; - } - } - } - - expr - } - /// Find the field named `name` in the field. Always return `Some` for convenience. fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> { let expr = &fields.iter() @@ -64,14 +51,14 @@ pub fn range(expr: &hir::Expr) -> Option { .unwrap_or_else(|| panic!("missing {} field for range", name)) .expr; - Some(unwrap_unstable(expr)) + Some(expr) } // The range syntax is expanded to literal paths starting with `core` or `std` depending on // `#[no_std]`. Testing both instead of resolving the paths. - match unwrap_unstable(expr).node { - hir::ExprPath(None, ref path) => { + match expr.node { + hir::ExprPath(ref path) => { if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) { Some(Range { start: None, @@ -168,10 +155,10 @@ pub enum VecArgs<'a> { pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option> { if_let_chain!{[ let hir::ExprCall(ref fun, ref args) = expr.node, - let hir::ExprPath(_, ref path) = fun.node, - let Some(fun_def) = resolve_node(cx, fun.id), + let hir::ExprPath(ref path) = fun.node, is_expn_of(cx, fun.span, "vec").is_some(), ], { + let fun_def = resolve_node(cx, path, fun.id); return if match_def_path(cx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 { // `vec![elem; size]` case Some(VecArgs::Repeat(&args[0], &args[1])) diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 1199f87ae3c..5c1f4014bee 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re), - (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()), + (&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.name.as_str() == r.name.as_str()), (&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr), (&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => { lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr) @@ -82,7 +82,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { }) } (&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) => - both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()) + both(&li, &ri, |l, r| l.name.as_str() == r.name.as_str()) && both(le, re, |l, r| self.eq_expr(l, r)), (&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r), (&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => { @@ -118,11 +118,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), - (&ExprPath(ref l_qself, ref l_subpath), &ExprPath(ref r_qself, ref r_subpath)) => { - both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath) - } + (&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r), (&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => { - self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && + self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) && over(lf, rf, |l, r| self.eq_field(l, r)) } (&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup), @@ -153,14 +151,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r), (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => { - self.eq_path(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs + self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs } - (&PatKind::Binding(ref lb, ref li, ref lp), &PatKind::Binding(ref rb, ref ri, ref rp)) => { - lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) - } - (&PatKind::Path(ref ql, ref l), &PatKind::Path(ref qr, ref r)) => { - both(ql, qr, |ql, qr| self.eq_qself(ql, qr)) && self.eq_path(l, r) + (&PatKind::Binding(ref lb, ref ld, ref li, ref lp), &PatKind::Binding(ref rb, ref rd, ref ri, ref rp)) => { + lb == rb && ld == rd && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r)) } + (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r), (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r), (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => { ls == rs && over(l, r, |l, r| self.eq_pat(l, r)) @@ -178,6 +174,18 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } } + fn eq_qpath(&self, left: &QPath, right: &QPath) -> bool { + match (left, right) { + (&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => { + both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath) + }, + (&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => { + self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg) + }, + _ => false, + } + } + fn eq_path(&self, left: &Path, right: &Path) -> bool { left.global == right.global && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) @@ -208,10 +216,6 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { self.eq_path_parameters(&left.parameters, &right.parameters) } - fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool { - left.ty.node == right.ty.node && left.position == right.position - } - fn eq_ty(&self, left: &Ty, right: &Ty) -> bool { match (&left.node, &right.node) { (&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec), @@ -222,9 +226,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) } - (&TyPath(ref lq, ref l_path), &TyPath(ref rq, ref r_path)) => { - both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path) - } + (&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, r), (&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)), (&TyInfer, &TyInfer) => true, _ => false, @@ -318,7 +320,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_) -> _ = ExprAgain; c.hash(&mut self.s); if let Some(i) = i { - self.hash_name(&i.node); + self.hash_name(&i.name); } } ExprAssign(ref l, ref r) => { @@ -350,7 +352,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _) -> _ = ExprBreak; c.hash(&mut self.s); if let Some(i) = i { - self.hash_name(&i.node); + self.hash_name(&i.name); } if let Some(ref j) = *j { self.hash_expr(&*j); @@ -452,16 +454,16 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } } - ExprPath(ref _qself, ref subpath) => { - let c: fn(_, _) -> _ = ExprPath; + ExprPath(ref qpath) => { + let c: fn(_) -> _ = ExprPath; c.hash(&mut self.s); - self.hash_path(subpath); + self.hash_qpath(qpath); } ExprStruct(ref path, ref fields, ref expr) => { let c: fn(_, _, _) -> _ = ExprStruct; c.hash(&mut self.s); - self.hash_path(path); + self.hash_qpath(path); for f in fields { self.hash_name(&f.name.node); @@ -526,6 +528,23 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { n.as_str().hash(&mut self.s); } + pub fn hash_qpath(&mut self, p: &QPath) { + match *p { + QPath::Resolved(ref _ty, ref path) => { + let c: fn(_, _) -> _ = QPath::Resolved; + c.hash(&mut self.s); + // self.hash_ty(ty); FIXME + self.hash_path(path); + }, + QPath::TypeRelative(ref _ty, ref seg) => { + let c: fn(_, _) -> _ = QPath::TypeRelative; + c.hash(&mut self.s); + // self.hash_ty(ty); FIXME + self.hash_name(&seg.name); + }, + } + } + pub fn hash_path(&mut self, p: &Path) { p.global.hash(&mut self.s); for p in &p.segments { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 70f47abb54f..b297aec7c07 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -275,11 +275,14 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { println!("{}index expr:", ind); print_expr(cx, idx, indent + 1); }, - hir::ExprPath(ref sel, ref path) => { - println!("{}Path, {}", ind, ty); - println!("{}self: {:?}", ind, sel); + hir::ExprPath(hir::QPath::Resolved(ref ty, ref path)) => { + println!("{}Resolved Path, {:?}", ind, ty); println!("{}path: {:?}", ind, path); }, + hir::ExprPath(hir::QPath::TypeRelative(ref ty, ref seg)) => { + println!("{}Relative Path, {:?}", ind, ty); + println!("{}seg: {:?}", ind, seg); + } hir::ExprAddrOf(ref muta, ref e) => { println!("{}AddrOf, {}", ind, ty); println!("mutability: {:?}", muta); @@ -354,7 +357,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("weird extern crate without a crate id"); } } - hir::ItemUse(ref path) => println!("{:?}", path.node), + hir::ItemUse(ref path, ref kind) => println!("{:?}, {:?}", path, kind), hir::ItemStatic(..) => println!("static item of type {:#?}", cx.tcx.item_type(did)), hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.item_type(did)), hir::ItemFn(..) => { @@ -383,13 +386,11 @@ fn print_item(cx: &LateContext, item: &hir::Item) { println!("trait has no default impl"); } }, - hir::ItemDefaultImpl(_, ref trait_ref) => { - let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id(); - println!("default impl for `{}`", cx.tcx.item_path_str(trait_did)); + hir::ItemDefaultImpl(_, ref _trait_ref) => { + println!("default impl"); }, - hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => { - let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id(); - println!("impl of trait `{}`", cx.tcx.item_path_str(trait_did)); + hir::ItemImpl(_, _, _, Some(ref _trait_ref), _, _) => { + println!("trait impl"); }, hir::ItemImpl(_, _, _, None, _, _) => { println!("impl"); @@ -402,7 +403,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { println!("{}+", ind); match pat.node { hir::PatKind::Wild => println!("{}Wild", ind), - hir::PatKind::Binding(ref mode, ref name, ref inner) => { + hir::PatKind::Binding(ref mode, _, ref name, ref inner) => { println!("{}Binding", ind); println!("{}mode: {:?}", ind, mode); println!("{}name: {}", ind, name.node); @@ -434,11 +435,14 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { print_pat(cx, field, indent + 1); } }, - hir::PatKind::Path(ref sel, ref path) => { - println!("{}Path", ind); - println!("{}self: {:?}", ind, sel); + hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => { + println!("{}Resolved Path, {:?}", ind, ty); println!("{}path: {:?}", ind, path); }, + hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => { + println!("{}Relative Path, {:?}", ind, ty); + println!("{}seg: {:?}", ind, seg); + }, hir::PatKind::Tuple(ref pats, opt_dots_position) => { println!("{}Tuple", ind); if let Some(dot_position) = opt_dots_position { diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 93d1ce8629b..a510adefb71 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -140,7 +140,7 @@ impl LateLintPass for LintWithoutLintPass { fn is_lint_ref_type(ty: &Ty) -> bool { if let TyRptr(Some(_), MutTy { ty: ref inner, mutbl: MutImmutable }) = ty.node { - if let TyPath(None, ref path) = inner.node { + if let TyPath(ref path) = inner.node { return match_path(path, &paths::LINT); } } @@ -149,7 +149,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool { fn is_lint_array_type(ty: &Ty) -> bool { - if let TyPath(None, ref path) = ty.node { + if let TyPath(ref path) = ty.node { match_path(path, &paths::LINT_ARRAY) } else { false diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 47d693e03b2..68d91301b2c 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,6 +1,7 @@ use reexport::*; use rustc::hir::*; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc::hir::def::Def; use rustc::hir::map::Node; use rustc::lint::{LintContext, LateContext, Level, Lint}; use rustc::session::Session; @@ -202,7 +203,15 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool /// ``` /// match_path(path, &["std", "rt", "begin_unwind"]) /// ``` -pub fn match_path(path: &Path, segments: &[&str]) -> bool { +pub fn match_path(path: &QPath, segments: &[&str]) -> bool { + if let QPath::Resolved(_, ref path) = *path { + match_path_old(path, segments) + } else { + false + } +} + +pub fn match_path_old(path: &Path, segments: &[&str]) -> bool { path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name == *b) } @@ -283,8 +292,8 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, } /// Resolve the definition of a node from its `NodeId`. -pub fn resolve_node(cx: &LateContext, id: NodeId) -> Option { - cx.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) +pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: NodeId) -> def::Def { + cx.tcx.tables().qpath_def(qpath, id) } /// Match an `Expr` against a chain of methods, and return the matched `Expr`s. @@ -736,8 +745,8 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, env: Node /// Return whether a pattern is refutable. pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { - fn is_enum_variant(cx: &LateContext, did: NodeId) -> bool { - matches!(cx.tcx.def_map.borrow().get(&did).map(|d| d.full_def()), Some(def::Def::Variant(..)) | Some(def::Def::VariantCtor(..))) + fn is_enum_variant(cx: &LateContext, qpath: &QPath, did: NodeId) -> bool { + matches!(cx.tcx.tables().qpath_def(qpath, did), def::Def::Variant(..) | def::Def::VariantCtor(..)) } fn are_refutable<'a, I: Iterator>(cx: &LateContext, mut i: I) -> bool { @@ -748,17 +757,17 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool { PatKind::Binding(..) | PatKind::Wild => false, PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, - PatKind::Path(..) => is_enum_variant(cx, pat.id), + PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.id), PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), - PatKind::Struct(_, ref fields, _) => { - if is_enum_variant(cx, pat.id) { + PatKind::Struct(ref qpath, ref fields, _) => { + if is_enum_variant(cx, qpath, pat.id) { true } else { are_refutable(cx, fields.iter().map(|field| &*field.node.pat)) } } - PatKind::TupleStruct(_, ref pats, _) => { - if is_enum_variant(cx, pat.id) { + PatKind::TupleStruct(ref qpath, ref pats, _) => { + if is_enum_variant(cx, qpath, pat.id) { true } else { are_refutable(cx, pats.iter().map(|pat| &**pat)) @@ -793,3 +802,20 @@ pub fn remove_blocks(expr: &Expr) -> &Expr { expr } } + +pub fn opt_def_id(def: Def) -> Option { + match def { + Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | + Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) | + Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) | + Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | + Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => { + Some(id) + } + + Def::Label(..) | + Def::PrimTy(..) | + Def::SelfTy(..) | + Def::Err => None, + } +}