diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb5df200f06..97bfbfda7606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## 0.0.105 — 2016-12-15 +* Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)* +* New lints: [`deref_addrof`], [`double_parens`], [`pub_enum_variant_names`] +* Fix suggestion in [`new_without_default`] +* FP fix in [`absurd_extreme_comparisons`] + ## 0.0.104 — 2016-12-15 * Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)* diff --git a/Cargo.toml b/Cargo.toml index 0b1d7fd8671b..d614a2389ef2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.104" +version = "0.0.105" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -25,7 +25,7 @@ test = false [dependencies] # begin automatic update -clippy_lints = { version = "0.0.104", path = "clippy_lints" } +clippy_lints = { version = "0.0.105", path = "clippy_lints" } # end automatic update [dev-dependencies] diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index faf86875f40d..2792ca16d627 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "clippy_lints" # begin automatic update -version = "0.0.104" +version = "0.0.105" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index de13c0264e50..f14268f9b4c1 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tcx.tables().expr_ty(array); if let ty::TyArray(_, size) = ty.sty { - let size = ConstInt::Infer(size as u64); + let size = ConstInt::Infer(size as u128); // Index is a constant uint let const_index = eval_const_expr_partial(cx.tcx, index, ExprTypeChecked, None); diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index df6ef64a73f8..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 { - MethodTraitItem(_, None) => true, - MethodTraitItem(_, 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/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 5b860d8cedc7..1323ce29875b 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -106,7 +106,7 @@ fn invert_cmp(cmp: BinOp_) -> BinOp_ { } -fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64, span: &Span) { +fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u128, span: &Span) { if let ExprBinary(ref op, ref left, ref right) = bit_op.node { if op.node != BiBitAnd && op.node != BiBitOr { return; @@ -117,7 +117,7 @@ fn check_compare(cx: &LateContext, bit_op: &Expr, cmp_op: BinOp_, cmp_value: u64 } } -fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u64, cmp_value: u64, span: &Span) { +fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: u128, cmp_value: u128, span: &Span) { match cmp_op { BiEq | BiNe => { match bit_op { @@ -212,7 +212,7 @@ fn check_bit_mask(cx: &LateContext, bit_op: BinOp_, cmp_op: BinOp_, mask_value: } } -fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { +fn check_ineffective_lt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { if c.is_power_of_two() && m < c { span_lint(cx, INEFFECTIVE_BIT_MASK, @@ -224,7 +224,7 @@ fn check_ineffective_lt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) } } -fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) { +fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str) { if (c + 1).is_power_of_two() && m <= c { span_lint(cx, INEFFECTIVE_BIT_MASK, @@ -236,7 +236,7 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u64, c: u64, op: &str) } } -fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { +fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { match lit.node { ExprLit(ref lit_ptr) => { if let LitKind::Int(value, _) = lit_ptr.node { diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 2f9a6b161585..6a02e69a8818 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -57,9 +57,10 @@ 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); - if matches!(expr.node, ExprBlock(_)) { - self.found_block = Some(expr); + let body = self.cx.tcx.map.body(eid); + let ex = &body.value; + if matches!(ex.node, ExprBlock(_)) { + self.found_block = Some(ex); return; } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 44288e7d7fcd..1f31cb0b2ecd 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -74,7 +74,7 @@ impl PartialEq for Constant { (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, (&Constant::Char(l), &Constant::Char(r)) => l == r, (&Constant::Int(l), &Constant::Int(r)) => { - l.is_negative() == r.is_negative() && l.to_u64_unchecked() == r.to_u64_unchecked() + l.is_negative() == r.is_negative() && l.to_u128_unchecked() == r.to_u128_unchecked() }, (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => { // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have @@ -110,7 +110,7 @@ impl Hash for Constant { c.hash(state); }, Constant::Int(i) => { - i.to_u64_unchecked().hash(state); + i.to_u128_unchecked().hash(state); i.is_negative().hash(state); }, Constant::Float(ref f, _) => { @@ -185,6 +185,7 @@ pub fn lit_to_constant(lit: &LitKind) -> Constant { LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), + LitKind::Int(value, LitIntType::Unsigned(UintTy::U128)) => Constant::Int(ConstInt::U128(value as u128)), LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => { Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))) }, @@ -192,6 +193,7 @@ pub fn lit_to_constant(lit: &LitKind) -> Constant { LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), + LitKind::Int(value, LitIntType::Signed(IntTy::I128)) => Constant::Int(ConstInt::I128(value as i128)), LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => { Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))) }, @@ -258,8 +260,14 @@ 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, number_id) => { + if let Some(lcx) = self.lcx { + self.binop_apply(value, + &lcx.tcx.map.body(number_id).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 897a578f19a7..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 MethodTraitItem(_, 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..896efb438458 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -42,9 +42,12 @@ 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(body_id) = 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(body_id).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..192898032994 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,7 +1,7 @@ use rustc::lint::*; use rustc::ty; use rustc::hir::*; -use utils::{snippet_opt, span_lint_and_then, is_adjusted}; +use utils::{snippet_opt, span_lint_and_then, is_adjusted, iter_input_pats}; #[allow(missing_copy_implementations)] pub struct EtaPass; @@ -49,7 +49,8 @@ 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 body = cx.tcx.map.body(eid); + let ex = &body.value; if let ExprCall(ref caller, ref args) = ex.node { if args.len() != decl.inputs.len() { // Not the same number of arguments, there @@ -71,7 +72,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { }, _ => (), } - for (a1, a2) in decl.inputs.iter().zip(args) { + for (a1, a2) in iter_input_pats(decl, body).zip(args) { if let PatKind::Binding(_, _, ident, _) = a1.pat.node { // XXXManishearth Should I be checking the binding mode here? if let ExprPath(QPath::Resolved(None, ref p)) = a2.node { 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 5ad676e57a08..2d85f2dd3cbf 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -6,7 +6,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::abi::Abi; use syntax::codemap::Span; -use utils::{span_lint, type_is_unsafe_function}; +use utils::{span_lint, type_is_unsafe_function, iter_input_pats}; /// **What it does:** Checks for functions with too many parameters. /// @@ -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,19 +102,19 @@ 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, nodeid); } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) { - if let hir::MethodTraitItem(ref sig, eid) = item.node { + if let hir::TraitItemKind::Method(ref sig, ref eid) = item.node { // don't lint extern functions decls, it's not their fault if sig.abi == Abi::Rust { self.check_arg_number(cx, &sig.decl, item.span); } - if let Some(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 body = cx.tcx.map.body(eid); + self.check_raw_ptr(cx, sig.unsafety, &sig.decl, body, item.id); } } } @@ -136,11 +136,15 @@ impl<'a, 'tcx> Functions { cx: &LateContext<'a, 'tcx>, unsafety: hir::Unsafety, decl: &'tcx hir::FnDecl, - expr: &'tcx hir::Expr, + body: &'tcx hir::Body, nodeid: ast::NodeId ) { + let expr = &body.value; if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) { - let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::>(); + let raw_ptrs = iter_input_pats(decl, body) + .zip(decl.inputs.iter()) + .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty)) + .collect::>(); if !raw_ptrs.is_empty() { let mut v = DerefVisitor { @@ -154,8 +158,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(arg: &hir::Arg, ty: &hir::Ty) -> Option { + if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) { Some(def_id) } else { None diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 22835b488403..fa4a5bf67573 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -87,23 +87,24 @@ 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 { +fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef]) { + fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool { &*item.name.as_str() == name && - if let MethodTraitItem(ref sig, _) = item.node { - if sig.decl.has_self() { - sig.decl.inputs.len() == 1 - } else { - false + if let AssociatedItemKind::Method { has_self } = item.kind { + has_self && + { + let did = cx.tcx.map.local_def_id(item.id.node_id); + let impl_ty = cx.tcx.item_type(did); + impl_ty.fn_args().skip_binder().len() == 1 } } else { false } } - if !trait_items.iter().any(|i| is_named_self(i, "is_empty")) { - if let Some(i) = trait_items.iter().find(|i| is_named_self(i, "len")) { - if cx.access_levels.is_exported(i.id) { + if !trait_items.iter().any(|i| is_named_self(cx, i, "is_empty")) { + if let Some(i) = trait_items.iter().find(|i| is_named_self(cx, i, "len")) { + if cx.access_levels.is_exported(i.id.node_id) { span_lint(cx, LEN_WITHOUT_IS_EMPTY, i.span, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index ac92d5ec97bc..cdcb271d8d75 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -3,10 +3,12 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(custom_attribute)] +#![feature(i128_type)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] #![feature(repeat_str)] +#![feature(conservative_impl_trait)] #![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)] #![allow(needless_lifetimes)] diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index fa0afd90d332..3006e5fc9b0d 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - if let MethodTraitItem(ref sig, _) = item.node { + if let TraitItemKind::Method(ref sig, _) = item.node { check_fn_inner(cx, &sig.decl, &sig.generics, item.span); } } @@ -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..311eb16514b9 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,7 +2,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::ast; use utils::{is_adjusted, match_path, match_trait_method, match_type, remove_blocks, paths, snippet, - span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth}; + span_help_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, iter_input_pats}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// @@ -31,18 +31,20 @@ 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 body = cx.tcx.map.body(closure_eid); + let closure_expr = remove_blocks(&body.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(first_arg) = iter_input_pats(decl, body).next(), + let Some(arg_ident) = get_arg_name(&first_arg.pat), // 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(&first_arg.pat)).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 +92,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 591b395fe709..8f1c6e4e9d1a 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,7 +1,6 @@ use rustc::hir; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::middle::const_qualif::ConstQualif; use rustc::ty; use rustc::hir::def::Def; use rustc_const_eval::EvalHint::ExprTypeChecked; @@ -12,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, is_self_ty, iter_input_pats}; use utils::paths; use utils::sugg; @@ -637,16 +636,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { let parent = cx.tcx.map.get_parent(implitem.id); let item = cx.tcx.map.expect_item(parent); if_let_chain! {[ - let hir::ImplItemKind::Method(ref sig, _) = implitem.node, - let Some(explicit_self) = sig.decl.inputs.get(0).and_then(hir::Arg::to_self), - let hir::ItemImpl(_, _, _, None, _, _) = item.node, + let hir::ImplItemKind::Method(ref sig, id) = implitem.node, + let Some(first_arg_ty) = sig.decl.inputs.get(0), + let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.map.body(id)).next(), + let hir::ItemImpl(_, _, _, None, ref self_ty, _) = item.node, ], { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if &*name.as_str() == method_name && sig.decl.inputs.len() == n_args && out_type.matches(&sig.decl.output) && - self_kind.matches(&explicit_self, false) { + self_kind.matches(&first_arg_ty, &first_arg, &self_ty, 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)); @@ -659,8 +659,7 @@ 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)), + !self_kinds.iter().any(|k| k.matches(&first_arg_ty, &first_arg, &self_ty, is_copy)), ], { let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION @@ -669,7 +668,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }; span_lint(cx, lint, - explicit_self.span, + first_arg.pat.span, &format!("methods called `{}` usually take {}; consider choosing a less \ ambiguous name", conv, @@ -685,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, + implitem.span, "methods called `new` usually return `Self`"); } }} @@ -752,11 +751,16 @@ 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? - if let Some(qualif) = cx.tcx.const_qualif_map.borrow().get(&arg.id) { - if !qualif.contains(ConstQualif::NOT_CONST) { - return; - } + let promotable = cx.tcx + .rvalue_promotable_to_static + .borrow() + .get(&arg.id) + .cloned() + .unwrap_or(true); + if promotable { + return; } + // (path, fn_has_argument, methods, suffix) let know_types: &[(&[_], _, &[_], _)] = &[(&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"), @@ -1338,7 +1342,7 @@ const PATTERN_METHODS: [(&'static str, usize); 17] = [ ]; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] enum SelfKind { Value, Ref, @@ -1347,27 +1351,36 @@ enum SelfKind { } impl SelfKind { - fn matches(self, slf: &hir::ExplicitSelf, allow_value_for_ref: bool) -> bool { - 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), + fn matches(self, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, allow_value_for_ref: bool) -> bool { + // Self types in the HIR are desugared to explicit self types. So it will always be `self: + // SomeType`, + // where SomeType can be `Self` or an explicit impl self type (e.g. `Foo` if the impl is on `Foo`) + // Thus, we only need to test equality against the impl self type or if it is an explicit + // `Self`. Furthermore, the only possible types for `self: ` are `&Self`, `Self`, `&mut Self`, + // and `Box`, including the equivalent types with `Foo`. + let is_actually_self = |ty| is_self_ty(ty) || ty == self_ty; + if is_self(arg) { + match self { + SelfKind::Value => is_actually_self(ty), + SelfKind::Ref | SelfKind::RefMut if allow_value_for_ref => is_actually_self(ty), + SelfKind::Ref | SelfKind::RefMut => { + match ty.node { + hir::TyRptr(_, ref mt_ty) => { + let mutability_match = if self == SelfKind::Ref { + mt_ty.mutbl == hir::MutImmutable + } else { + mt_ty.mutbl == hir::MutMutable + }; + is_actually_self(&mt_ty.ty) && mutability_match - _ => false, - } - } - - fn matches_explicit_type(self, ty: &hir::Ty, allow_value_for_ref: bool) -> bool { - match (self, &ty.node) { - (SelfKind::Value, &hir::TyPath(..)) | - (SelfKind::Ref, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutImmutable, .. })) | - (SelfKind::RefMut, &hir::TyRptr(_, hir::MutTy { mutbl: hir::Mutability::MutMutable, .. })) => true, - (SelfKind::Ref, &hir::TyPath(..)) | - (SelfKind::RefMut, &hir::TyPath(..)) => allow_value_for_ref, - _ => false, + }, + _ => false, + } + }, + _ => false, + } + } else { + self == SelfKind::No } } diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 409a7de86f06..4af47d731726 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -9,7 +9,7 @@ use rustc_const_eval::eval_const_expr_partial; use rustc_const_math::ConstFloat; use syntax::codemap::{Span, Spanned, ExpnFormat}; use utils::{get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path, snippet, - span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment}; + span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment, iter_input_pats}; use utils::sugg::Sugg; /// **What it does:** Checks for function arguments and let bindings denoted as `ref`. @@ -175,7 +175,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { cx: &LateContext<'a, 'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl, - _: &'tcx Expr, + body: &'tcx Body, _: Span, _: NodeId ) { @@ -183,7 +183,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // Does not apply to closures return; } - for arg in &decl.inputs { + for arg in iter_input_pats(decl, body) { if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node { span_lint(cx, TOPLEVEL_REF_ARG, diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 70696ea3908b..d5be44e8c2b9 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -136,9 +136,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) { let desc = match trait_item.node { - hir::ConstTraitItem(..) => "an associated constant", - hir::MethodTraitItem(..) => "a trait method", - hir::TypeTraitItem(..) => "an associated type", + hir::TraitItemKind::Const(..) => "an associated constant", + hir::TraitItemKind::Method(..) => "a trait method", + hir::TraitItemKind::Type(..) => "an associated type", }; self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc); diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 7e7733bed80c..6e27358836bc 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -42,7 +42,10 @@ 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 2f74390cc73e..78fdc06708a9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { } fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { - if let MethodTraitItem(ref sig, _) = item.node { + if let TraitItemKind::Method(ref sig, _) = item.node { check_fn(cx, &sig.decl, item.id); } } @@ -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..a16fe7ae0091 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -4,7 +4,7 @@ use rustc::hir::*; use rustc::hir::intravisit::{Visitor, FnKind, NestedVisitorMap}; use rustc::ty; use syntax::codemap::Span; -use utils::{higher, in_external_macro, snippet, span_lint_and_then}; +use utils::{higher, in_external_macro, snippet, span_lint_and_then, iter_input_pats}; /// **What it does:** Checks for bindings that shadow other bindings already in /// scope, while just changing reference level or mutability. @@ -85,25 +85,25 @@ 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); } } -fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, expr: &'tcx Expr) { +fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tcx Body) { let mut bindings = Vec::new(); - for arg in &decl.inputs { + for arg in iter_input_pats(decl, body) { if let PatKind::Binding(_, _, ident, _) = arg.pat.node { bindings.push((ident.node, ident.span)) } } - check_expr(cx, expr, &mut bindings); + check_expr(cx, &body.value, &mut bindings); } fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, bindings: &mut Vec<(Name, 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, body_id) => { check_ty(cx, fty, bindings); - check_expr(cx, expr, bindings); + check_expr(cx, &cx.tcx.map.body(body_id).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(body_id) => check_expr(cx, &cx.tcx.map.body(body_id).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 9912c52492a5..ae320db63bcd 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 { @@ -87,9 +87,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypePass { fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { match item.node { - ConstTraitItem(ref ty, _) | - TypeTraitItem(_, Some(ref ty)) => check_ty(cx, ty), - MethodTraitItem(ref sig, _) => check_fn_decl(cx, &sig.decl), + TraitItemKind::Const(ref ty, _) | + TraitItemKind::Type(_, Some(ref ty)) => check_ty(cx, ty), + TraitItemKind::Method(ref sig, _) => check_fn_decl(cx, &sig.decl), _ => (), } } @@ -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 { @@ -326,7 +326,7 @@ declare_lint! { /// **Example:** /// ```rust /// let y: i8 = -1; -/// y as u64 // will return 18446744073709551615 +/// y as u128 // will return 18446744073709551615 /// ``` declare_lint! { pub CAST_SIGN_LOSS, @@ -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 ) { @@ -624,9 +624,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexityPass { fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) { match item.node { - ConstTraitItem(ref ty, _) | - TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty), - MethodTraitItem(MethodSig { ref decl, .. }, None) => self.check_fndecl(cx, decl), + TraitItemKind::Const(ref ty, _) | + TraitItemKind::Type(_, Some(ref ty)) => self.check_type(cx, ty), + 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); @@ -889,12 +889,14 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option Minimum, + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) | + (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum, (&ty::TyBool, Bool(true)) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | @@ -903,12 +905,14 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option Maximum, + (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) | + (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MAX))) => Maximum, _ => return None, }; @@ -985,19 +989,19 @@ impl LintPass for InvalidUpcastComparisons { #[derive(Copy, Clone, Debug, Eq)] enum FullInt { - S(i64), - U(u64), + S(i128), + U(u128), } impl FullInt { #[allow(cast_sign_loss)] - fn cmp_s_u(s: i64, u: u64) -> Ordering { + fn cmp_s_u(s: i128, u: u128) -> Ordering { if s < 0 { Ordering::Less - } else if u > (i64::max_value() as u64) { + } else if u > (i128::max_value() as u128) { Ordering::Greater } else { - (s as u64).cmp(&u) + (s as u128).cmp(&u) } } } @@ -1034,20 +1038,22 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( match cx.tcx.tables().expr_ty(cast_exp).sty { TyInt(int_ty) => { Some(match int_ty { - IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), - IntTy::I16 => (FullInt::S(i16::min_value() as i64), FullInt::S(i16::max_value() as i64)), - IntTy::I32 => (FullInt::S(i32::min_value() as i64), FullInt::S(i32::max_value() as i64)), - IntTy::I64 => (FullInt::S(i64::min_value() as i64), FullInt::S(i64::max_value() as i64)), - IntTy::Is => (FullInt::S(isize::min_value() as i64), FullInt::S(isize::max_value() as i64)), + IntTy::I8 => (FullInt::S(i8::min_value() as i128), FullInt::S(i8::max_value() as i128)), + IntTy::I16 => (FullInt::S(i16::min_value() as i128), FullInt::S(i16::max_value() as i128)), + IntTy::I32 => (FullInt::S(i32::min_value() as i128), FullInt::S(i32::max_value() as i128)), + IntTy::I64 => (FullInt::S(i64::min_value() as i128), FullInt::S(i64::max_value() as i128)), + IntTy::I128 => (FullInt::S(i128::min_value() as i128), FullInt::S(i128::max_value() as i128)), + IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }) }, TyUint(uint_ty) => { Some(match uint_ty { - UintTy::U8 => (FullInt::U(u8::min_value() as u64), FullInt::U(u8::max_value() as u64)), - UintTy::U16 => (FullInt::U(u16::min_value() as u64), FullInt::U(u16::max_value() as u64)), - UintTy::U32 => (FullInt::U(u32::min_value() as u64), FullInt::U(u32::max_value() as u64)), - UintTy::U64 => (FullInt::U(u64::min_value() as u64), FullInt::U(u64::max_value() as u64)), - UintTy::Us => (FullInt::U(usize::min_value() as u64), FullInt::U(usize::max_value() as u64)), + UintTy::U8 => (FullInt::U(u8::min_value() as u128), FullInt::U(u8::max_value() as u128)), + UintTy::U16 => (FullInt::U(u16::min_value() as u128), FullInt::U(u16::max_value() as u128)), + UintTy::U32 => (FullInt::U(u32::min_value() as u128), FullInt::U(u32::max_value() as u128)), + UintTy::U64 => (FullInt::U(u64::min_value() as u128), FullInt::U(u64::max_value() as u128)), + UintTy::U128 => (FullInt::U(u128::min_value() as u128), FullInt::U(u128::max_value() as u128)), + UintTy::Us => (FullInt::U(usize::min_value() as u128), FullInt::U(usize::max_value() as u128)), }) }, _ => None, @@ -1067,8 +1073,8 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { Ok(val) => { if let Integral(const_int) = val { Some(match const_int.erase_type() { - ConstInt::InferSigned(x) => FullInt::S(x as i64), - ConstInt::Infer(x) => FullInt::U(x as u64), + ConstInt::InferSigned(x) => FullInt::S(x as i128), + ConstInt::Infer(x) => FullInt::U(x as u128), _ => unreachable!(), }) } else { 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..e330a662f97d 100644 --- a/clippy_lints/src/utils/hir.rs +++ b/clippy_lints/src/utils/hir.rs @@ -112,7 +112,10 @@ 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, ll_id), &ExprRepeat(ref re, rl_id)) => { + self.eq_expr(le, re) && + self.eq_expr(&self.cx.tcx.map.body(ll_id).value, &self.cx.tcx.map.body(rl_id).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 +186,8 @@ 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 +215,10 @@ 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, ll_id), &TyArray(ref rt, rl_id)) => { + self.eq_ty(lt, rt) && + self.eq_expr(&self.cx.tcx.map.body(ll_id).value, &self.cx.tcx.map.body(rl_id).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 +370,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 +431,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, l_id) => { 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(l_id).value); }, ExprRet(ref e) => { let c: fn(_) -> _ = ExprRet; @@ -524,7 +531,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..457008eb0ef2 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,19 @@ 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(_, body_id) => { println!("associated constant"); - print_expr(cx, e, 1); + print_expr(cx, &cx.tcx.map.body(body_id).value, 1); }, hir::ImplItemKind::Method(..) => println!("method"), hir::ImplItemKind::Type(_) => println!("associated type"), @@ -323,12 +327,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, body_id) => { 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(body_id).value, indent + 1); }, } } @@ -339,7 +343,10 @@ 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 +420,9 @@ 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 +435,9 @@ 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..ea7a654ed1f7 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, body_id) = 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(body_id).value); } } } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 77b33d7b5893..f971779b2edb 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, } @@ -610,7 +611,7 @@ pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { } /// Check whether the given expression is a constant literal of the given value. -pub fn is_integer_literal(expr: &Expr, value: u64) -> bool { +pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { // FIXME: use constant folding if let ExprLit(ref spanned) = expr.node { if let LitKind::Int(v, _) = spanned.node { @@ -896,3 +897,26 @@ 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 is_self_ty(slf: &Ty) -> bool { + if_let_chain! {[ + let TyPath(ref qp) = slf.node, + let QPath::Resolved(None, ref path) = *qp, + let Def::SelfTy(..) = path.def, + ], { + return true + }} + false +} + +pub fn iter_input_pats<'tcx>(decl: &FnDecl, body: &'tcx Body) -> impl Iterator { + (0..decl.inputs.len()).map(move |i| &body.arguments[i]) +}