diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 7fdd8d21205f..f5ba053d28ce 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -157,7 +157,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn is_relevant_item(cx: &LateContext, item: &Item) -> bool { if let ItemFn(_, _, _, _, _, eid) = item.node { - is_relevant_expr(cx, cx.tcx.map.expr(eid)) + is_relevant_expr(cx, &cx.tcx.map.body(eid).value) } else { false } @@ -165,15 +165,15 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool { fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool { match item.node { - ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.map.expr(eid)), + ImplItemKind::Method(_, eid) => is_relevant_expr(cx, &cx.tcx.map.body(eid).value), _ => false, } } fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool { match item.node { - TraitItemKind::Method(_, None) => true, - TraitItemKind::Method(_, Some(eid)) => is_relevant_expr(cx, cx.tcx.map.expr(eid)), + TraitItemKind::Method(_, TraitMethod::Required(_)) => true, + TraitItemKind::Method(_, TraitMethod::Provided(eid)) => is_relevant_expr(cx, &cx.tcx.map.body(eid).value), _ => false, } } diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 2f9a6b161585..2e2b6ee8b937 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -57,9 +57,9 @@ struct ExVisitor<'a, 'tcx: 'a> { 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); + let expr = self.cx.tcx.map.body(eid).value; if matches!(expr.node, ExprBlock(_)) { - self.found_block = Some(expr); + self.found_block = Some(&expr); return; } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 44288e7d7fcd..cb73d419eb24 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -258,8 +258,12 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprLit(ref lit) => Some(lit_to_constant(&lit.node)), ExprArray(ref vec) => self.multi(vec).map(Constant::Vec), ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple), - ExprRepeat(ref value, ref number) => { - self.binop_apply(value, number, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) + ExprRepeat(ref value, numberId) => { + if let Some(lcx) = self.lcx { + self.binop_apply(value, &lcx.tcx.map.body(numberId).value, |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) + } else { + None + } }, ExprUnary(op, ref operand) => { self.expr(operand).and_then(|o| { diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 34cd40a8fdf1..f2aabfca69e6 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -94,20 +94,20 @@ 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, cx.tcx.map.expr(eid), item.span); + self.check(cx, &cx.tcx.map.body(eid).value, 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); + self.check(cx, &cx.tcx.map.body(eid).value, item.span); } } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - if let TraitItemKind::Method(_, Some(eid)) = item.node { - self.check(cx, cx.tcx.map.expr(eid), item.span); + if let TraitItemKind::Method(_, TraitMethod::Provided(eid)) = item.node { + self.check(cx, &cx.tcx.map.body(eid).value, item.span); } } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index f4181da3c2b7..72a88be016e9 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -42,9 +42,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { if let ItemEnum(ref def, _) = item.node { for var in &def.variants { let variant = &var.node; - if let Some(ref disr) = variant.disr_expr { + if let Some(bodyId) = variant.disr_expr { use rustc_const_eval::*; - let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) { + let bad = match eval_const_expr_partial(cx.tcx, &cx.tcx.map.body(bodyId).value, EvalHint::ExprTypeChecked, None) { Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, _ => false, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index 80e17e37acb0..3384693c51ec 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -64,8 +64,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { &mut self, cx: &LateContext<'a, 'tcx>, _: visit::FnKind<'tcx>, - decl: &'tcx FnDecl, - body: &'tcx Expr, + _: &'tcx FnDecl, + body: &'tcx Body, _: Span, id: NodeId ) { @@ -82,7 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); { let mut vis = ExprUseVisitor::new(&mut v, &infcx); - vis.walk_fn(decl, body); + vis.consume_body(body); } for node in v.set { diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index f25014b6805e..a30cd87554c5 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -49,14 +49,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass { fn check_closure(cx: &LateContext, expr: &Expr) { if let ExprClosure(_, ref decl, eid, _) = expr.node { - let ex = cx.tcx.map.expr(eid); + let ex = cx.tcx.map.body(eid).value; if let ExprCall(ref caller, ref args) = ex.node { if args.len() != decl.inputs.len() { // Not the same number of arguments, there // is no way the closure is the same as the function return; } - if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { + if is_adjusted(cx, &ex) || args.iter().any(|arg| is_adjusted(cx, arg)) { // Are the expression or the arguments type-adjusted? Then we need the closure return; } @@ -72,7 +72,7 @@ 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.node { // XXXManishearth Should I be checking the binding mode here? if let ExprPath(QPath::Resolved(None, ref p)) = a2.node { if p.segments.len() != 1 { diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 1894a12a6d3e..7194f45d9501 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -81,7 +81,7 @@ pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Exp let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id), &*decl.name.as_str() == "__STATIC_FMTSTR", let ItemStatic(_, _, ref expr) = decl.node, - let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …] + let ExprAddrOf(_, ref expr) = cx.tcx.map.body(*expr).value.node, // &["…", "…", …] let ExprArray(ref exprs) = expr.node, ], { let mut result = Vec::new(); diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index eb666dcc5109..18bc644a2638 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { cx: &LateContext<'a, 'tcx>, kind: intravisit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, - expr: &'tcx hir::Expr, + body: &'tcx hir::Body, span: Span, nodeid: ast::NodeId ) { @@ -102,7 +102,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { } } - self.check_raw_ptr(cx, unsafety, decl, expr, nodeid); + self.check_raw_ptr(cx, unsafety, decl, &body.value, nodeid); } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { @@ -112,9 +112,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions { self.check_arg_number(cx, &sig.decl, item.span); } - if let Some(eid) = eid { - let expr = cx.tcx.map.expr(eid); - self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id); + if let hir::TraitMethod::Provided(eid) = eid { + let expr = cx.tcx.map.body(eid).value; + self.check_raw_ptr(cx, sig.unsafety, &sig.decl, &expr, item.id); } } } @@ -154,8 +154,8 @@ impl<'a, 'tcx> Functions { } } -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) { +fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option { + if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &cx.tcx.map.get(arg.id)) { Some(def_id) } else { None diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index ff19a59b5abe..42ba0ebfc402 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -4,7 +4,8 @@ use rustc::ty; use rustc::hir::*; use syntax::ast::{Lit, LitKind, Name}; use syntax::codemap::{Span, Spanned}; -use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty}; +use utils::{get_item_name, in_macro, snippet, span_lint, span_lint_and_then, walk_ptrs_ty, + is_self, has_self}; /// **What it does:** Checks for getting the length of something via `.len()` /// just to compare to zero, and suggests using `.is_empty()` where applicable. @@ -89,16 +90,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItem]) { fn is_named_self(item: &TraitItem, name: &str) -> bool { - &*item.name.as_str() == name && if let TraitItemKind::Method(ref sig, _) = item.node { - if sig.decl.has_self() { - sig.decl.inputs.len() == 1 - } else { - false - } - } else { - false + return has_self(&*sig.decl) && &*item.name.as_str() == name && sig.decl.inputs.len() == 1; } + false } if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 2a258ff5db77..2c3b06a98c4e 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -137,7 +137,7 @@ fn could_use_elision<'a, 'tcx: 'a, T: Iterator>( // extract lifetimes in input argument types for arg in &func.inputs { - input_visitor.visit_ty(&arg.ty); + input_visitor.visit_ty(&arg); } // extract lifetimes in output type if let Return(ref ty) = func.output { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index f04a4b32de2b..1418a18d3c55 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -31,18 +31,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if &*name.node.as_str() == "map" && args.len() == 2 { match args[1].node { ExprClosure(_, ref decl, closure_eid, _) => { - let closure_expr = remove_blocks(cx.tcx.map.expr(closure_eid)); + let closure_expr = remove_blocks(&cx.tcx.map.body(closure_eid).value); if_let_chain! {[ // nothing special in the argument, besides reference bindings // (e.g. .map(|&x| x) ) - let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), + let Some(arg_ident) = get_arg_name(&*decl.inputs[0]), // the method is being called on a known type (option or iterator) let Some(type_name) = get_type_name(cx, expr, &args[0]) ], { // look for derefs, for .map(|x| *x) if only_derefs(cx, &*closure_expr, arg_ident) && // .cloned() only removes one level of indirection, don't lint on more - walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&*decl.inputs[0].pat)).1 == 1 + walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&*decl.inputs[0])).1 == 1 { span_help_and_lint(cx, MAP_CLONE, expr.span, &format!( "you seem to be using .map() to clone the contents of an {}, consider \ @@ -90,7 +90,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool { name: id, parameters: PathParameters::none(), }]; - !path.global && path.segments[..] == arg_segment + !path.is_global() && path.segments[..] == arg_segment }, _ => false, } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 978e9f5a029f..f25b5d01cea8 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -219,10 +219,10 @@ fn check_single_match_opt_like( if inner.iter().any(|pat| pat.node != PatKind::Wild) { return; } - path.to_string() + print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) }, PatKind::Binding(BindByValue(MutImmutable), _, ident, None) => ident.node.to_string(), - PatKind::Path(ref path) => path.to_string(), + PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), _ => return, }; diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 6d9860d92fdf..c6986cb5456e 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -11,7 +11,7 @@ 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, last_path_segment, single_segment_path, - match_def_path}; + match_def_path, is_self}; use utils::paths; use utils::sugg; @@ -645,7 +645,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if &*name.as_str() == method_name && sig.decl.inputs.len() == n_args && out_type.matches(&sig.decl.output) && - self_kind.matches(&first_arg, false) { + self_kind.matches(&**first_arg, false) { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); @@ -658,8 +658,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { for &(ref conv, self_kinds) in &CONVENTIONS { if_let_chain! {[ conv.check(&name.as_str()), - let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), - !self_kinds.iter().any(|k| k.matches(&explicit_self, is_copy)), + let Some(explicit_self) = sig.decl.inputs.get(0), + !self_kinds.iter().any(|k| k.matches(&**explicit_self, is_copy)), ], { let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION @@ -684,7 +684,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { !ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem.id)) { span_lint(cx, NEW_RET_NO_SELF, - explicit_self.span, + first_arg.span, "methods called `new` usually return `Self`"); } }} @@ -751,7 +751,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: ) { // don't lint for constant values // FIXME: can we `expect` here instead of match? - let promotable = cx.tcx().rvalue_promotable_to_static.borrow() + let promotable = cx.tcx.rvalue_promotable_to_static.borrow() .get(&arg.id).cloned().unwrap_or(true); if !promotable { return; @@ -1338,7 +1338,7 @@ const PATTERN_METHODS: [(&'static str, usize); 17] = [ ]; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] enum SelfKind { Value, Ref, @@ -1348,18 +1348,19 @@ enum SelfKind { impl SelfKind { fn matches(self, slf: &hir::Arg, allow_value_for_ref: bool) -> bool { - if !slf.has_self() { - return self == No; - } - match (self, &slf.node) { - (SelfKind::Value, &hir::SelfKind::Value(_)) | - (SelfKind::Ref, &hir::SelfKind::Region(_, hir::Mutability::MutImmutable)) | - (SelfKind::RefMut, &hir::SelfKind::Region(_, hir::Mutability::MutMutable)) => true, - (SelfKind::Ref, &hir::SelfKind::Value(_)) | - (SelfKind::RefMut, &hir::SelfKind::Value(_)) => allow_value_for_ref, - (_, &hir::SelfKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), + if is_self(slf) { + match (self, &slf.pat.node) { + (SelfKind::Value, &hir::PatKind::Binding(hir::BindingMode::BindByValue(_), ..)) | + (SelfKind::Ref, &hir::PatKind::Ref(_, hir::Mutability::MutImmutable)) | + (SelfKind::RefMut, &hir::PatKind::Ref(_, hir::Mutability::MutMutable)) => true, + (SelfKind::Ref, &hir::PatKind::Binding(hir::BindingMode::BindByRef(hir::Mutability::MutImmutable), ..)) | + (SelfKind::RefMut, &hir::PatKind::Binding(hir::BindingMode::BindByRef(hir::Mutability::MutMutable), ..)) => allow_value_for_ref, +// (_, &hir::PatKind::Explicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref), - _ => false, + _ => false, + } + } else { + self == SelfKind::No } } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 409a7de86f06..e81b9c989cd4 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { cx: &LateContext<'a, 'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl, - _: &'tcx Expr, + _: &'tcx Body, _: Span, _: NodeId ) { @@ -184,10 +184,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { return; } for arg in &decl.inputs { - if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node { + if let PatKind::Binding(BindByRef(_), _, _, _) = arg.node { span_lint(cx, TOPLEVEL_REF_ARG, - arg.pat.span, + arg.span, "`ref` directly on a function argument is ignored. Consider using a reference type instead."); } } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 7e7733bed80c..a181c33ebb96 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> 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 { - check_arguments(cx, arguments, function_type, &path.to_string()); + check_arguments(cx, arguments, function_type, &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); } }, ExprMethodCall(ref name, _, ref arguments) => { diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index de71586863ae..5477204b79c1 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { cx: &LateContext<'a, 'tcx>, kind: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - _: &'tcx hir::Expr, + _: &'tcx hir::Body, span: Span, id: ast::NodeId ) { diff --git a/clippy_lints/src/ok_if_let.rs b/clippy_lints/src/ok_if_let.rs index 65b13688ff62..ec5da909d60a 100644 --- a/clippy_lints/src/ok_if_let.rs +++ b/clippy_lints/src/ok_if_let.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { ], { let is_result_type = match_type(cx, cx.tcx.tables().expr_ty(&result_types[0]), &paths::RESULT); let some_expr_string = snippet(cx, y[0].span, ""); - if print::path_to_string(x) == "Some" && is_result_type { + if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type { span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span, "Matching on `Some` with `ok()` is redundant", &format!("Consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string)); diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 0b7bf3c30963..78fdc06708a9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -99,13 +99,13 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { if match_type(cx, ty, &paths::VEC) { span_lint(cx, PTR_ARG, - arg.ty.span, + arg.span, "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \ with non-Vec-based slices. Consider changing the type to `&[...]`"); } else if match_type(cx, ty, &paths::STRING) { span_lint(cx, PTR_ARG, - arg.ty.span, + arg.span, "writing `&String` instead of `&str` involves a new object where a slice will do. \ Consider changing the type to `&str`"); } diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 9c5b032f6251..17160a5a1244 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -85,21 +85,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { cx: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, decl: &'tcx FnDecl, - expr: &'tcx Expr, + body: &'tcx Body, _: Span, _: NodeId ) { - if in_external_macro(cx, expr.span) { + if in_external_macro(cx, body.value.span) { return; } - check_fn(cx, decl, expr); + check_fn(cx, decl, &body.value); } } fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, expr: &'tcx 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.node { bindings.push((ident.node, ident.span)) } } @@ -341,9 +341,9 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V match ty.node { TyObjectSum(ref sty, _) | TySlice(ref sty) => check_ty(cx, sty, bindings), - TyArray(ref fty, ref expr) => { + TyArray(ref fty, bodyId) => { check_ty(cx, fty, bindings); - check_expr(cx, expr, bindings); + check_expr(cx, &cx.tcx.map.body(bodyId).value, bindings); }, TyPtr(MutTy { ty: ref mty, .. }) | TyRptr(_, MutTy { ty: ref mty, .. }) => check_ty(cx, mty, bindings), @@ -352,7 +352,7 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut V check_ty(cx, t, bindings) } }, - TyTypeof(ref expr) => check_expr(cx, expr, bindings), + TyTypeof(bodyId) => check_expr(cx, &cx.tcx.map.body(bodyId).value, bindings), _ => (), } } @@ -371,7 +371,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool { } fn path_eq_name(name: Name, path: &Path) -> bool { - !path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() + !path.is_global() && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str() } struct ContainsSelf<'a, 'tcx: 'a> { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 327e638d9b84..0b8308933f1b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -70,7 +70,7 @@ impl LintPass for TypePass { } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { - fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, id: NodeId) { + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Body, _: Span, id: NodeId) { // skip trait implementations, see #605 if let Some(map::NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent(id)) { if let ItemImpl(_, _, _, Some(..), _, _) = item.node { @@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { for input in &decl.inputs { - check_ty(cx, &input.ty); + check_ty(cx, &input); } if let FunctionRetTy::Return(ref ty) = decl.output { @@ -601,7 +601,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { cx: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, decl: &'tcx FnDecl, - _: &'tcx Expr, + _: &'tcx Body, _: Span, _: NodeId ) { @@ -626,7 +626,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { match item.node { TraitItemKind::Const(ref ty, _) | TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), - TraitItemKind::Method(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl), + TraitItemKind::Method(MethodSig { ref decl, .. }, TraitMethod::Required(_)) => self.check_fndecl(cx, decl), // methods with default impl are covered by check_fn _ => (), } @@ -651,7 +651,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { impl<'a, 'tcx> TypeComplexityPass { fn check_fndecl(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl) { for arg in &decl.inputs { - self.check_type(cx, &arg.ty); + self.check_type(cx, &arg); } if let Return(ref ty) = decl.output { self.check_type(cx, ty); diff --git a/clippy_lints/src/unused_label.rs b/clippy_lints/src/unused_label.rs index 9017fd6933e8..5136a821c546 100644 --- a/clippy_lints/src/unused_label.rs +++ b/clippy_lints/src/unused_label.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { cx: &LateContext<'a, 'tcx>, kind: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body: &'tcx hir::Expr, + body: &'tcx hir::Body, span: Span, fn_id: ast::NodeId ) { @@ -58,7 +58,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel { cx: cx, labels: HashMap::new(), }; - walk_fn(&mut v, kind, decl, body.expr_id(), span, fn_id); + walk_fn(&mut v, kind, decl, body.id(), span, fn_id); for (label, span) in v.labels { span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label)); diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir.rs index 80399825b6d1..643b52496543 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { !self.ignore_fn && l_name.node == r_name.node && over(l_tys, r_tys, |l, r| self.eq_ty(l, r)) && self.eq_exprs(l_args, r_args) }, - (&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl), + (&ExprRepeat(ref le, llId), &ExprRepeat(ref re, rlId)) => self.eq_expr(le, re) && self.eq_expr(&self.cx.tcx.map.body(llId).value, &self.cx.tcx.map.body(rlId).value), (&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)), (&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)) => { @@ -183,7 +183,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { } 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)) + left.is_global() == right.is_global() && over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)) } fn eq_path_parameters(&self, left: &PathParameters, right: &PathParameters) -> bool { @@ -211,7 +211,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { 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), - (&TyArray(ref lt, ref ll), &TyArray(ref rt, ref rl)) => self.eq_ty(lt, rt) && self.eq_expr(ll, rl), + (&TyArray(ref lt, llId), &TyArray(ref rt, rlId)) => self.eq_ty(lt, rt) && self.eq_expr(&self.cx.tcx.map.body(llId).value, &self.cx.tcx.map.body(rlId).value), (&TyPtr(ref l_mut), &TyPtr(ref r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty), (&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty) @@ -363,7 +363,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { let c: fn(_, _, _, _) -> _ = ExprClosure; c.hash(&mut self.s); cap.hash(&mut self.s); - self.hash_expr(self.cx.tcx.map.expr(eid)); + self.hash_expr(&self.cx.tcx.map.body(eid).value); }, ExprField(ref e, ref f) => { let c: fn(_, _) -> _ = ExprField; @@ -424,11 +424,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { self.hash_name(&name.node); self.hash_exprs(args); }, - ExprRepeat(ref e, ref l) => { + ExprRepeat(ref e, lId) => { let c: fn(_, _) -> _ = ExprRepeat; c.hash(&mut self.s); self.hash_expr(e); - self.hash_expr(l); + self.hash_expr(&self.cx.tcx.map.body(lId).value); }, ExprRet(ref e) => { let c: fn(_) -> _ = ExprRet; @@ -524,7 +524,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> { } pub fn hash_path(&mut self, p: &Path) { - p.global.hash(&mut self.s); + p.is_global().hash(&mut self.s); for p in &p.segments { self.hash_name(&p.name); } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 79cf15b6c5f5..220d4572e81d 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -4,6 +4,7 @@ use rustc::lint::*; use rustc::hir; +use rustc::hir::print; use syntax::ast::Attribute; use syntax::attr; @@ -52,16 +53,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", path), + hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false))), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } if item.defaultness.is_default() { println!("default"); } match item.node { - hir::ImplItemKind::Const(_, ref e) => { + hir::ImplItemKind::Const(_, bodyId) => { println!("associated constant"); - print_expr(cx, e, 1); + print_expr(cx, &cx.tcx.map.body(bodyId).value, 1); }, hir::ImplItemKind::Method(..) => println!("method"), hir::ImplItemKind::Type(_) => println!("associated type"), @@ -323,12 +324,12 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) { print_expr(cx, base, indent + 1); } }, - hir::ExprRepeat(ref val, ref n) => { + hir::ExprRepeat(ref val, bodyId) => { println!("{}Repeat, {}", ind, ty); println!("{}value:", ind); print_expr(cx, val, indent + 1); println!("{}repeat count:", ind); - print_expr(cx, n, indent + 1); + print_expr(cx, &cx.tcx.map.body(bodyId).value, indent + 1); }, } } @@ -339,7 +340,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) { match item.vis { hir::Visibility::Public => println!("public"), hir::Visibility::Crate => println!("visible crate wide"), - hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", path), + hir::Visibility::Restricted { ref path, .. } => println!("visible in module `{}`", print::to_string(print::NO_ANN, |s| s.print_path(path, false))), hir::Visibility::Inherited => println!("visibility inherited from outer item"), } match item.node { @@ -413,7 +414,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { }, hir::PatKind::Struct(ref path, ref fields, ignore) => { println!("{}Struct", ind); - println!("{}name: {}", ind, path); + println!("{}name: {}", ind, print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); println!("{}ignore leftover fields: {}", ind, ignore); println!("{}fields:", ind); for field in fields { @@ -426,7 +427,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) { }, hir::PatKind::TupleStruct(ref path, ref fields, opt_dots_position) => { println!("{}TupleStruct", ind); - println!("{}path: {}", ind, path); + println!("{}path: {}", ind, print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); if let Some(dot_position) = opt_dots_position { println!("{}dot position: {}", ind, dot_position); } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index cf9e90d62bd4..d2da4f9085b9 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -106,7 +106,7 @@ impl LintPass for LintWithoutLintPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if let ItemStatic(ref ty, MutImmutable, ref expr) = item.node { + if let ItemStatic(ref ty, MutImmutable, bodyId) = item.node { if is_lint_ref_type(ty) { self.declared_lints.insert(item.name, item.span); } else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" { @@ -114,7 +114,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass { output: &mut self.registered_lints, cx: cx, }; - collector.visit_expr(expr); + collector.visit_expr(&cx.tcx.map.body(bodyId).value); } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 77b33d7b5893..e9c77f027e84 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -19,6 +19,7 @@ use syntax::attr; use syntax::codemap::{ExpnFormat, ExpnInfo, MultiSpan, Span, DUMMY_SP}; use syntax::errors::DiagnosticBuilder; use syntax::ptr::P; +use syntax::symbol::keywords; pub mod cargo; pub mod comparisons; @@ -487,7 +488,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI match node { Node::NodeBlock(block) => Some(block), Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. }) => { - match cx.tcx.map.expr(eid).node { + match cx.tcx.map.body(eid).value.node { ExprBlock(ref block) => Some(block), _ => None, } @@ -896,3 +897,15 @@ pub fn opt_def_id(def: Def) -> Option { Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, } } + +pub fn is_self(slf: &Arg) -> bool { + if let PatKind::Binding(_, _, name, _) = slf.pat.node { + name.node == keywords::SelfValue.name() + } else { + false + } +} + +pub fn has_self(slf: &FnDecl) -> bool { + slf.inputs.get(0).map(|arg| is_self(&arg)).unwrap_or(false) +}