diff --git a/CHANGELOG.md b/CHANGELOG.md index e062ae640c0f..837f160f770d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,36 @@ # Change Log All notable changes to this project will be documented in this file. -## 0.0.136 - 2017-05-26 +## 0.0.139 — 2017-06-10 +* Update to *rustc 1.19.0-nightly (4bf5c99af 2017-06-10)* +* Fix bugs with for loop desugaring +* Check for AsRef/AsMut arguments in wrong_self_convention + +## 0.0.138 — 2017-06-05 +* Update to *rustc 1.19.0-nightly (0418fa9d3 2017-06-04)* + +## 0.0.137 — 2017-06-05 +* Update to *rustc 1.19.0-nightly (6684d176c 2017-06-03)* + +## 0.0.136 — 2017—05—26 * Update to *rustc 1.19.0-nightly (557967766 2017-05-26)* -## 0.0.135 - 2017-05-24 +## 0.0.135 — 2017—05—24 * Update to *rustc 1.19.0-nightly (5b13bff52 2017-05-23)* -## 0.0.134 - 2017-05-19 +## 0.0.134 — 2017—05—19 * Update to *rustc 1.19.0-nightly (0ed1ec9f9 2017-05-18)* -## 0.0.133 - 2017-05-14 +## 0.0.133 — 2017—05—14 * Update to *rustc 1.19.0-nightly (826d8f385 2017-05-13)* -## 0.0.132 - 2017-05-05 +## 0.0.132 — 2017—05—05 * Fix various bugs and some ices -## 0.0.131 - 2017-05-04 +## 0.0.131 — 2017—05—04 * Update to *rustc 1.19.0-nightly (2d4ed8e0c 2017-05-03)* -## 0.0.130 - 2017-05-03 +## 0.0.130 — 2017—05—03 * Update to *rustc 1.19.0-nightly (6a5fc9eec 2017-05-02)* ## 0.0.129 — 2017-05-01 diff --git a/Cargo.toml b/Cargo.toml index e2bf05640089..51778cd38713 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.0.136" +version = "0.0.139" authors = [ "Manish Goregaokar ", "Andre Bogus ", @@ -31,7 +31,7 @@ test = false [dependencies] # begin automatic update -clippy_lints = { version = "0.0.136", path = "clippy_lints" } +clippy_lints = { version = "0.0.139", path = "clippy_lints" } # end automatic update cargo_metadata = "0.2" diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index aa7d2b96e17a..1a32116b73e2 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.136" +version = "0.0.139" # end automatic update authors = [ "Manish Goregaokar ", diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 3432ce59c7d1..07d838bef2ed 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -82,14 +82,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if op.node == binop.node { let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { - let ty = cx.tables.expr_ty(assignee); - if ty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } - let rty = cx.tables.expr_ty(rhs); - if rty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } span_lint_and_then(cx, MISREFACTORED_ASSIGN_OP, expr.span, @@ -120,13 +112,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { #[allow(cyclomatic_complexity)] let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { let ty = cx.tables.expr_ty(assignee); - if ty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } let rty = cx.tables.expr_ty(rhs); - if rty.walk_shallow().next().is_some() { - return; // implements_trait does not work with generics - } macro_rules! ops { ($op:expr, $cx:expr, @@ -152,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { let hir::Item_::ItemImpl(_, _, _, _, Some(ref trait_ref), _, _) = item.node, trait_ref.path.def.def_id() == trait_id ], { return; }} - implements_trait($cx, $ty, trait_id, &[$rty], None) + implements_trait($cx, $ty, trait_id, &[$rty]) },)* _ => false, } diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index e89a997ec032..88f0ef0955c3 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -3,7 +3,7 @@ use reexport::*; use rustc::lint::*; use rustc::hir::*; -use rustc::ty; +use rustc::ty::{self, TyCtxt}; use semver::Version; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::codemap::Span; @@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { } } -fn is_relevant_item(tcx: ty::TyCtxt, item: &Item) -> bool { +fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool { if let ItemFn(_, _, _, _, _, eid) = item.node { is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value) } else { @@ -166,14 +166,14 @@ fn is_relevant_item(tcx: ty::TyCtxt, item: &Item) -> bool { } } -fn is_relevant_impl(tcx: ty::TyCtxt, item: &ImplItem) -> bool { +fn is_relevant_impl(tcx: TyCtxt, item: &ImplItem) -> bool { match item.node { ImplItemKind::Method(_, eid) => is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value), _ => false, } } -fn is_relevant_trait(tcx: ty::TyCtxt, item: &TraitItem) -> bool { +fn is_relevant_trait(tcx: TyCtxt, item: &TraitItem) -> bool { match item.node { TraitItemKind::Method(_, TraitMethod::Required(_)) => true, TraitItemKind::Method(_, TraitMethod::Provided(eid)) => { @@ -183,7 +183,7 @@ fn is_relevant_trait(tcx: ty::TyCtxt, item: &TraitItem) -> bool { } } -fn is_relevant_block(tcx: ty::TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool { +fn is_relevant_block(tcx: TyCtxt, tables: &ty::TypeckTables, block: &Block) -> bool { if let Some(stmt) = block.stmts.first() { match stmt.node { StmtDecl(_, _) => true, @@ -195,7 +195,7 @@ fn is_relevant_block(tcx: ty::TyCtxt, tables: &ty::TypeckTables, block: &Block) } } -fn is_relevant_expr(tcx: ty::TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool { +fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool { match expr.node { ExprBlock(ref block) => is_relevant_block(tcx, tables, block), ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index e0418be7aa6b..c338189cefe0 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -385,10 +385,12 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> { e.span, "this boolean expression can be simplified", |db| { - db.span_suggestions(e.span, "try", improvements.into_iter().map(|suggestion| { - suggest(self.cx, suggestion, &h2q.terminals) - }).collect()); - }); + db.span_suggestions(e.span, + "try", + improvements.into_iter() + .map(|suggestion| suggest(self.cx, suggestion, &h2q.terminals)) + .collect()); + }); } } } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index e094e8da3fca..c68642da3b62 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -5,7 +5,7 @@ use rustc::hir::def::Def; use rustc_const_eval::lookup_const_by_id; use rustc_const_math::ConstInt; use rustc::hir::*; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, TyCtxt, Ty}; use rustc::ty::subst::{Substs, Subst}; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; @@ -161,7 +161,7 @@ impl PartialOrd for Constant { /// parse a `LitKind` to a `Constant` #[allow(cast_possible_wrap)] -pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: ty::Ty<'tcx>) -> Constant { +pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: Ty<'tcx>) -> Constant { use syntax::ast::*; use syntax::ast::LitIntType::*; use rustc::ty::util::IntTypeExt; @@ -286,9 +286,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let substs = self.tables - .node_id_item_substs(id) - .unwrap_or_else(|| self.tcx.intern_substs(&[])); + let substs = self.tables.node_substs(id); let substs = if self.substs.is_empty() { substs } else { diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 6fe089cf9165..8f8bdf472a5c 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,5 +1,5 @@ use rustc::lint::*; -use rustc::ty; +use rustc::ty::Ty; use rustc::hir::*; use std::collections::HashMap; use std::collections::hash_map::Entry; @@ -251,12 +251,8 @@ fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { } /// Return the list of bindings in a pattern. -fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { - fn bindings_impl<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - pat: &Pat, - map: &mut HashMap> - ) { +fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap> { + fn bindings_impl<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat, map: &mut HashMap>) { match pat.node { PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => bindings_impl(cx, pat, map), diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index e9fd654eebf8..f6642db8fec2 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,6 +1,5 @@ use rustc::lint::*; -use rustc::ty::TypeVariants; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc::hir::*; use syntax::codemap::Span; use utils::paths; @@ -89,7 +88,7 @@ fn check_hash_peq<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, - ty: ty::Ty<'tcx>, + ty: Ty<'tcx>, hash_is_automatically_derived: bool ) { if_let_chain! {[ @@ -134,28 +133,27 @@ fn check_hash_peq<'a, 'tcx>( } /// 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>) { +fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: Ty<'tcx>) { if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) { - let def_id = cx.tcx.hir.local_def_id(item.id); - if !is_copy(cx, ty, def_id) { + if !is_copy(cx, ty) { return; } match ty.sty { - TypeVariants::TyAdt(def, _) if def.is_union() => return, + ty::TyAdt(def, _) if def.is_union() => return, // Some types are not Clone by default but could be cloned “by hand” if necessary - TypeVariants::TyAdt(def, substs) => { + ty::TyAdt(def, substs) => { for variant in &def.variants { for field in &variant.fields { match field.ty(cx.tcx, substs).sty { - TypeVariants::TyArray(_, size) if size > 32 => { + ty::TyArray(_, size) if size > 32 => { return; }, - TypeVariants::TyFnPtr(..) => { + ty::TyFnPtr(..) => { return; }, - TypeVariants::TyTuple(tys, _) if tys.len() > 12 => { + ty::TyTuple(tys, _) if tys.len() > 12 => { return; }, _ => (), diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index e5064febe954..6112aec7cb6a 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -135,8 +135,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, &msg, arg.span, - &format!("argument has type {}", arg_ty.sty)); - } else if is_copy(cx, arg_ty, cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(arg.id))) { + &format!("argument has type {}", arg_ty)); + } else if is_copy(cx, arg_ty) { if match_def_path(cx.tcx, def_id, &paths::DROP) { lint = DROP_COPY; msg = DROP_COPY_SUMMARY.to_string(); @@ -151,7 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { expr.span, &msg, arg.span, - &format!("argument has type {}", arg_ty.sty)); + &format!("argument has type {}", arg_ty)); } }} } diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 0bd1740c5459..12b588967f8a 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) { // only check top level `use` statements for item in &m.item_ids { - self.lint_item(cx, cx.krate.item(item.id)); + self.lint_item(cx, cx.tcx.hir.expect_item(item.id)); } } } diff --git a/clippy_lints/src/eq_op.rs b/clippy_lints/src/eq_op.rs index 894ba09f50fa..10e5f2ba7c05 100644 --- a/clippy_lints/src/eq_op.rs +++ b/clippy_lints/src/eq_op.rs @@ -75,8 +75,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { BiNe | BiEq => (cx.tcx.lang_items.eq_trait(), true), BiLt | BiLe | BiGe | BiGt => (cx.tcx.lang_items.ord_trait(), true), }; - let parent = cx.tcx.hir.get_parent(e.id); - let parent = cx.tcx.hir.local_def_id(parent); if let Some(trait_id) = trait_id { #[allow(match_same_arms)] match (&left.node, &right.node) { @@ -87,10 +85,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { (&ExprAddrOf(_, ref l), &ExprAddrOf(_, ref r)) => { let lty = cx.tables.expr_ty(l); let rty = cx.tables.expr_ty(r); - let lcpy = is_copy(cx, lty, parent); - let rcpy = is_copy(cx, rty, parent); + let lcpy = is_copy(cx, lty); + let rcpy = is_copy(cx, rty); // either operator autorefs or both args are copyable - if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty], None) { + if (requires_ref || (lcpy && rcpy)) && implements_trait(cx, lty, trait_id, &[rty]) { span_lint_and_then(cx, OP_REF, e.span, @@ -100,17 +98,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { let rsnip = snippet(cx, r.span, "...").to_string(); multispan_sugg(db, "use the values directly".to_string(), - vec![(left.span, lsnip), - (right.span, rsnip)]); + vec![(left.span, lsnip), (right.span, rsnip)]); }) - } else if lcpy && !rcpy && - implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)], None) { + } else if lcpy && !rcpy && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion(left.span, "use the left value directly", lsnip); }) - } else if !lcpy && rcpy && - implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty], None) { + } else if !lcpy && rcpy && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) { span_lint_and_then(cx, OP_REF, e.span, @@ -124,9 +119,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { // &foo == bar (&ExprAddrOf(_, ref l), _) => { let lty = cx.tables.expr_ty(l); - let lcpy = is_copy(cx, lty, parent); - if (requires_ref || lcpy) && - implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)], None) { + let lcpy = is_copy(cx, lty); + if (requires_ref || lcpy) && implements_trait(cx, lty, trait_id, &[cx.tables.expr_ty(right)]) { span_lint_and_then(cx, OP_REF, e.span, "needlessly taken reference of left operand", |db| { let lsnip = snippet(cx, l.span, "...").to_string(); db.span_suggestion(left.span, "use the left value directly", lsnip); @@ -136,9 +130,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp { // foo == &bar (_, &ExprAddrOf(_, ref r)) => { let rty = cx.tables.expr_ty(r); - let rcpy = is_copy(cx, rty, parent); - if (requires_ref || rcpy) && - implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty], None) { + let rcpy = is_copy(cx, rty); + if (requires_ref || rcpy) && implements_trait(cx, cx.tables.expr_ty(left), trait_id, &[rty]) { span_lint_and_then(cx, OP_REF, e.span, "taken reference of right operand", |db| { let rsnip = snippet(cx, r.span, "...").to_string(); db.span_suggestion(right.span, "use the right value directly", rsnip); diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index a36951b5f365..c3a3f37fab59 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -4,13 +4,11 @@ use rustc::hir::map::Node::{NodeExpr, NodeStmt}; use rustc::lint::*; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt, Categorization}; -use rustc::ty; -use rustc::ty::layout::TargetDataLayout; -use rustc::traits::Reveal; +use rustc::ty::{self, Ty}; use rustc::util::nodemap::NodeSet; use syntax::ast::NodeId; use syntax::codemap::Span; -use utils::span_lint; +use utils::{span_lint, type_size}; pub struct Pass { pub too_large_for_stack: u64, @@ -39,15 +37,13 @@ declare_lint! { "using `Box` where unnecessary" } -fn is_non_trait_box(ty: ty::Ty) -> bool { +fn is_non_trait_box(ty: Ty) -> bool { ty.is_box() && !ty.boxed_ty().is_trait() } struct EscapeDelegate<'a, 'tcx: 'a> { + cx: &'a LateContext<'a, 'tcx>, set: NodeSet, - tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, - tables: &'a ty::TypeckTables<'tcx>, - target: TargetDataLayout, too_large_for_stack: u64, } @@ -67,23 +63,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { _: Span, node_id: NodeId ) { - // we store the infcx because it is expensive to recreate - // the context each time. + let fn_def_id = cx.tcx.hir.local_def_id(node_id); let mut v = EscapeDelegate { + cx: cx, set: NodeSet(), - tcx: cx.tcx, - tables: cx.tables, - target: TargetDataLayout::parse(cx.sess()), too_large_for_stack: self.too_large_for_stack, }; - let infcx = cx.tcx.borrowck_fake_infer_ctxt(body.id()); - let fn_def_id = cx.tcx.hir.local_def_id(node_id); let region_maps = &cx.tcx.region_maps(fn_def_id); - { - let mut vis = ExprUseVisitor::new(&mut v, region_maps, &infcx); - vis.consume_body(body); - } + ExprUseVisitor::new(&mut v, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); for node in v.set { span_lint(cx, @@ -94,20 +82,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } } -impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { +impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn consume(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, mode: ConsumeMode) { if let Categorization::Local(lid) = cmt.cat { - if self.set.contains(&lid) { - if let Move(DirectRefMove) = mode { - // moved out or in. clearly can't be localized - self.set.remove(&lid); - } + if let Move(DirectRefMove) = mode { + // moved out or in. clearly can't be localized + self.set.remove(&lid); } } } fn matched_pat(&mut self, _: &Pat, _: cmt<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: cmt<'tcx>, _: ConsumeMode) { - let map = &self.tcx.hir; + let map = &self.cx.tcx.hir; if map.is_argument(consume_pat.id) { // Skip closure arguments if let Some(NodeExpr(..)) = map.find(map.get_parent_node(consume_pat.id)) { @@ -147,51 +133,24 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { } } - fn borrow( - &mut self, - borrow_id: NodeId, - _: Span, - cmt: cmt<'tcx>, - _: ty::Region, - _: ty::BorrowKind, - loan_cause: LoanCause - ) { - use rustc::ty::adjustment::Adjust; - + fn borrow(&mut self, _: NodeId, _: Span, cmt: cmt<'tcx>, _: ty::Region, _: ty::BorrowKind, loan_cause: LoanCause) { if let Categorization::Local(lid) = cmt.cat { - if self.set.contains(&lid) { - if let Some(&Adjust::DerefRef { autoderefs, .. }) = - self.tables - .adjustments - .get(&borrow_id) - .map(|a| &a.kind) { - if LoanCause::AutoRef == loan_cause { - // x.foo() - if autoderefs == 0 { - self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) - } - } else { - span_bug!(cmt.span, "Unknown adjusted AutoRef"); - } - } else if LoanCause::AddrOf == loan_cause { - // &x - if let Some(&Adjust::DerefRef { autoderefs, .. }) = - self.tables - .adjustments - .get(&self.tcx - .hir - .get_parent_node(borrow_id)) - .map(|a| &a.kind) { - if autoderefs <= 1 { - // foo(&x) where no extra autoreffing is happening - self.set.remove(&lid); - } - } + match loan_cause { + // x.foo() + // Used without autodereffing (i.e. x.clone()) + LoanCause::AutoRef | - } else if LoanCause::MatchDiscriminant == loan_cause { - self.set.remove(&lid); // `match x` can move + // &x + // foo(&x) where no extra autoreffing is happening + LoanCause::AddrOf | + + // `match x` can move + LoanCause::MatchDiscriminant => { + self.set.remove(&lid); } + // do nothing for matches, etc. These can't escape + _ => {} } } } @@ -199,18 +158,12 @@ impl<'a, 'tcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn mutate(&mut self, _: NodeId, _: Span, _: cmt<'tcx>, _: MutateMode) {} } -impl<'a, 'tcx: 'a> EscapeDelegate<'a, 'tcx> { - fn is_large_box(&self, ty: ty::Ty<'tcx>) -> bool { +impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { + fn is_large_box(&self, ty: Ty<'tcx>) -> bool { // Large types need to be boxed to avoid stack // overflows. if ty.is_box() { - let inner = ty.boxed_ty(); - self.tcx.infer_ctxt((), Reveal::All).enter(|infcx| if let Ok(layout) = inner.layout(&infcx) { - let size = layout.size(&self.target); - size.bytes() > self.too_large_for_stack - } else { - false - }) + type_size(self.cx, ty.boxed_ty()).unwrap_or(0) > self.too_large_for_stack } else { false } diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 9f694dd1cff7..36cae6968d44 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -137,11 +137,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { } }, ExprMethodCall(..) => { - let method_call = ty::MethodCall::expr(e.id); let borrowed_table = self.cx.tables; - let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); - let result_ty = method_type.ty.fn_ret(); - if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&result_ty).sty { + if borrowed_table.expr_ty(e).is_never() { self.report_diverging_sub_expr(e); } }, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 3a6a316226cb..e7dbc3250f78 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::hir::map::Node::NodeItem; use rustc::lint::*; -use rustc::ty::TypeVariants; +use rustc::ty; use syntax::ast::LitKind; use syntax::symbol::InternedString; use utils::paths; @@ -132,7 +132,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool { ], { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); - return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING); + return ty.sty == ty::TyStr || match_type(cx, ty, &paths::STRING); }} false diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 0c4712a59117..463358c99b46 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -1,6 +1,5 @@ use rustc::hir::intravisit; use rustc::hir; -use rustc::ty; use rustc::lint::*; use std::collections::HashSet; use syntax::ast; @@ -184,8 +183,8 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> { } }, hir::ExprMethodCall(_, _, ref args) => { - let method_call = ty::MethodCall::expr(expr.id); - let base_type = self.cx.tables.method_map[&method_call].ty; + let def_id = self.cx.tables.type_dependent_defs[&expr.id].def_id(); + let base_type = self.cx.tcx.type_of(def_id); if type_is_unsafe_function(base_type) { for arg in args { diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index e57feaa5937c..7bac29f6808f 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -58,14 +58,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { } } - +#[allow(cast_possible_wrap)] fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { 0 => v.to_u128_unchecked() == 0, - -1 => match v.int_type() { - SignedInt(_) => #[allow(cast_possible_wrap)] (v.to_u128_unchecked() as i128 == -1), - UnsignedInt(_) => false + -1 => { + match v.int_type() { + SignedInt(_) => (v.to_u128_unchecked() as i128 == -1), + UnsignedInt(_) => false, + } }, 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 148eb616be0c..611987ae1630 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -95,7 +95,7 @@ fn check_trait_items(cx: &LateContext, item: &Item, trait_items: &[TraitItemRef] { let did = cx.tcx.hir.local_def_id(item.id.node_id); let impl_ty = cx.tcx.type_of(did); - impl_ty.fn_args().skip_binder().len() == 1 + impl_ty.fn_sig().inputs().skip_binder().len() == 1 } } else { false @@ -122,7 +122,7 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) { { let did = cx.tcx.hir.local_def_id(item.id.node_id); let impl_ty = cx.tcx.type_of(did); - impl_ty.fn_args().skip_binder().len() == 1 + impl_ty.fn_sig().inputs().skip_binder().len() == 1 } } else { false diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6a0e8b70fd66..fc9bcbab73af 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -7,7 +7,8 @@ use rustc::hir::map::Node::NodeBlock; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::region::CodeExtent; -use rustc::ty; +use rustc::ty::{self, Ty}; +use rustc::ty::subst::Subst; use rustc_const_eval::ConstContext; use std::collections::HashMap; use syntax::ast; @@ -739,13 +740,11 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) { lint_iter_method(cx, args, arg, &method_name); } } else if method_name == "into_iter" && match_trait_method(cx, arg, &paths::INTO_ITERATOR) { - let method_call = ty::MethodCall::expr(arg.id); - let fn_ty = cx.tables - .method_map - .get(&method_call) - .map(|method_callee| method_callee.ty) - .expect("method calls need an entry in the method map"); - let fn_arg_tys = fn_ty.fn_args(); + let def_id = cx.tables.type_dependent_defs[&arg.id].def_id(); + let substs = cx.tables.node_substs(arg.id); + let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); + + let fn_arg_tys = method_type.fn_sig().inputs(); assert_eq!(fn_arg_tys.skip_binder().len(), 1); if fn_arg_tys.skip_binder()[0].is_region_ptr() { lint_iter_method(cx, args, arg, &method_name); @@ -1049,7 +1048,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool { match_type(cx, ty, &paths::BTREESET) } -fn is_iterable_array(ty: ty::Ty) -> bool { +fn is_iterable_array(ty: Ty) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { ty::TyArray(_, 0...32) => true, diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 6b721a970a60..ba4d24b1d62b 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -2,8 +2,8 @@ use rustc::lint::*; use rustc::hir::*; use rustc::ty; 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, iter_input_pats}; +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, iter_input_pats}; /// **What it does:** Checks for mapping `clone()` over an iterator. /// diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index f8f50bfb8536..3e9e2d06d054 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -1,7 +1,7 @@ use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc_const_eval::ConstContext; use rustc_const_math::ConstInt; use std::cmp::Ordering; @@ -226,14 +226,7 @@ fn report_single_match_single_pattern(cx: &LateContext, ex: &Expr, arms: &[Arm], }); } -fn check_single_match_opt_like( - cx: &LateContext, - ex: &Expr, - arms: &[Arm], - expr: &Expr, - ty: ty::Ty, - els: Option<&Expr> -) { +fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr, ty: Ty, els: Option<&Expr>) { // list of candidate Enums we know will never get any more members let candidates = &[(&paths::COW, "Borrowed"), (&paths::COW, "Cow::Borrowed"), diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 738350a4af98..08400600bb42 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc::hir::def::Def; use rustc_const_eval::ConstContext; use std::borrow::Cow; @@ -10,7 +10,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, is_self, is_self_ty, iter_input_pats}; + match_def_path, is_self, is_self_ty, iter_input_pats, match_path_old}; use utils::paths; use utils::sugg; @@ -649,7 +649,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if name == method_name && sig.decl.inputs.len() == n_args && out_type.matches(&sig.decl.output) && - self_kind.matches(first_arg_ty, first_arg, self_ty, false) { + self_kind.matches(first_arg_ty, first_arg, self_ty, false, &sig.generics) { 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,11 +659,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { // check conventions w.r.t. conversion method names and predicates let def_id = cx.tcx.hir.local_def_id(item.id); let ty = cx.tcx.type_of(def_id); - let is_copy = is_copy(cx, ty, def_id); + let is_copy = is_copy(cx, ty); for &(ref conv, self_kinds) in &CONVENTIONS { if_let_chain! {[ conv.check(&name.as_str()), - !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy)), + !self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy, &sig.generics)), ], { let lint = if item.vis == hir::Visibility::Public { WRONG_PUB_SELF_CONVENTION @@ -684,9 +684,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { } let ret_ty = return_ty(cx, implitem.id); - let implitem_defid = cx.tcx.hir.local_def_id(implitem.id); if name == "new" && - !ret_ty.walk().any(|t| same_tys(cx, t, ty, implitem_defid)) { + !ret_ty.walk().any(|t| same_tys(cx, t, ty)) { span_lint(cx, NEW_RET_NO_SELF, implitem.span, @@ -725,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: return false; }; - if implements_trait(cx, arg_ty, default_trait_id, &[], None) { + if implements_trait(cx, arg_ty, default_trait_id, &[]) { span_lint_and_then(cx, OR_FUN_CALL, span, @@ -820,9 +819,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir: } /// Checks for the `CLONE_ON_COPY` lint. -fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: ty::Ty) { +fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: Ty) { let ty = cx.tables.expr_ty(expr); - let parent = cx.tcx.hir.get_parent(expr.id); if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty { if let ty::TyRef(..) = inner.sty { span_lint_and_then(cx, @@ -839,7 +837,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t } } - if is_copy(cx, ty, cx.tcx.hir.local_def_id(parent)) { + if is_copy(cx, ty) { span_lint_and_then(cx, CLONE_ON_COPY, expr.span, @@ -979,8 +977,8 @@ fn lint_iter_skip_next(cx: &LateContext, expr: &hir::Expr) { } } -fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option> { - fn may_slice(cx: &LateContext, ty: ty::Ty) -> bool { +fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option> { + fn may_slice(cx: &LateContext, ty: Ty) -> bool { match ty.sty { ty::TySlice(_) => true, ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), @@ -1253,7 +1251,7 @@ fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) } /// Given a `Result` type, return its error type (`E`). -fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option> { +fn get_error_type<'a>(cx: &LateContext, ty: Ty<'a>) -> Option> { if let ty::TyAdt(_, substs) = ty.sty { if match_type(cx, ty, &paths::RESULT) { substs.types().nth(1) @@ -1266,9 +1264,9 @@ fn get_error_type<'a>(cx: &LateContext, ty: ty::Ty<'a>) -> Option> { } /// This checks whether a given type is known to implement Debug. -fn has_debug_impl<'a, 'b>(ty: ty::Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { +fn has_debug_impl<'a, 'b>(ty: Ty<'a>, cx: &LateContext<'b, 'a>) -> bool { match cx.tcx.lang_items.debug_trait() { - Some(debug) => implements_trait(cx, ty, debug, &[], None), + Some(debug) => implements_trait(cx, ty, debug, &[]), None => false, } } @@ -1353,7 +1351,14 @@ enum SelfKind { } impl SelfKind { - fn matches(self, ty: &hir::Ty, arg: &hir::Arg, self_ty: &hir::Ty, allow_value_for_ref: bool) -> bool { + fn matches( + self, + ty: &hir::Ty, + arg: &hir::Arg, + self_ty: &hir::Ty, + allow_value_for_ref: bool, + generics: &hir::Generics + ) -> 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`) @@ -1384,7 +1389,12 @@ impl SelfKind { _ => false, } } else { - self == SelfKind::No + match self { + SelfKind::Value => false, + SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT), + SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT), + SelfKind::No => true, + } } } @@ -1398,6 +1408,44 @@ impl SelfKind { } } +fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool { + single_segment_ty(ty).map_or(false, |seg| { + generics.ty_params.iter().any(|param| { + param.name == seg.name && + param.bounds.iter().any(|bound| if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound { + let path = &ptr.trait_ref.path; + match_path_old(path, name) && + path.segments.last().map_or(false, |s| if let hir::PathParameters::AngleBracketedParameters(ref data) = + s.parameters { + data.types.len() == 1 && (is_self_ty(&data.types[0]) || is_ty(&*data.types[0], self_ty)) + } else { + false + }) + } else { + false + }) + }) + }) +} + +fn is_ty(ty: &hir::Ty, self_ty: &hir::Ty) -> bool { + match (&ty.node, &self_ty.node) { + (&hir::TyPath(hir::QPath::Resolved(_, ref ty_path)), + &hir::TyPath(hir::QPath::Resolved(_, ref self_ty_path))) => { + ty_path.segments.iter().map(|seg| seg.name).eq(self_ty_path.segments.iter().map(|seg| seg.name)) + }, + _ => false, + } +} + +fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> { + if let hir::TyPath(ref path) = ty.node { + single_segment_path(path) + } else { + None + } +} + impl Convention { fn check(&self, other: &str) -> bool { match *self { diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index b5acafac1698..02ccdb2d79b8 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -455,13 +455,13 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr) { // *arg impls PartialEq if !arg_ty .builtin_deref(true, ty::LvaluePreference::NoPreference) - .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty], None)) + .map_or(false, |tam| implements_trait(cx, tam.ty, partial_eq_trait_id, &[other_ty])) // arg impls PartialEq<*other> && !other_ty .builtin_deref(true, ty::LvaluePreference::NoPreference) - .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty], None)) + .map_or(false, |tam| implements_trait(cx, arg_ty, partial_eq_trait_id, &[tam.ty])) // arg impls PartialEq - && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty], None) { + && !implements_trait(cx, arg_ty, partial_eq_trait_id, &[other_ty]) { return; } @@ -514,13 +514,13 @@ fn in_attributes_expansion(expr: &Expr) -> bool { /// Test whether `def` is a variable defined outside a macro. fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { match *def { - def::Def::Local(id) | - def::Def::Upvar(id, _, _) => { - if let Some(span) = cx.tcx.hir.span_if_local(id) { - !in_macro(span) - } else { - true - } + def::Def::Local(def_id) | + def::Def::Upvar(def_id, _, _) => { + let id = cx.tcx + .hir + .as_local_node_id(def_id) + .expect("local variables should be found in the same crate"); + !in_macro(cx.tcx.hir.span(id)) }, _ => false, } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 681bbc42a6f7..fc3107c3068d 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,7 +1,7 @@ use rustc::hir; use rustc::hir::intravisit; use rustc::lint::*; -use rustc::ty::{TypeAndMut, TyRef}; +use rustc::ty; use utils::{higher, in_external_macro, span_lint}; /// **What it does:** Checks for instances of `mut mut` references. @@ -68,7 +68,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible"); - } else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty { + } else if let ty::TyRef(_, ty::TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tables.expr_ty(e).sty { span_lint(self.cx, MUT_MUT, expr.span, diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index 07c941ecee6b..034e49a016c0 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,5 +1,6 @@ use rustc::lint::*; -use rustc::ty::{TypeAndMut, TypeVariants, MethodCall, TyS}; +use rustc::ty::{self, Ty}; +use rustc::ty::subst::Subst; use rustc::hir::*; use utils::span_lint; @@ -34,44 +35,40 @@ impl LintPass for UnnecessaryMutPassed { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { - let borrowed_table = cx.tables; match e.node { ExprCall(ref fn_expr, ref arguments) => { - let function_type = borrowed_table.node_types - .get(&fn_expr.id) - .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, + cx.tables.expr_ty(fn_expr), &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))); } }, ExprMethodCall(ref name, _, ref arguments) => { - let method_call = MethodCall::expr(e.id); - let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen."); - check_arguments(cx, arguments, method_type.ty, &name.node.as_str()) + let def_id = cx.tables.type_dependent_defs[&e.id].def_id(); + let substs = cx.tables.node_substs(e.id); + let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs); + check_arguments(cx, arguments, method_type, &name.node.as_str()) }, _ => (), } } } -fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: &TyS, name: &str) { +fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: Ty, name: &str) { match type_definition.sty { - TypeVariants::TyFnDef(_, _, fn_type) | - TypeVariants::TyFnPtr(fn_type) => { + ty::TyFnDef(_, _, fn_type) | + ty::TyFnPtr(fn_type) => { let parameters = fn_type.skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { - TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) | - TypeVariants::TyRawPtr(TypeAndMut { mutbl: MutImmutable, .. }) => { + ty::TyRef(_, ty::TypeAndMut { mutbl: MutImmutable, .. }) | + ty::TyRawPtr(ty::TypeAndMut { mutbl: MutImmutable, .. }) => { if let ExprAddrOf(MutMutable, _) = argument.node { span_lint(cx, UNNECESSARY_MUT_PASSED, argument.span, - &format!("The function/method \"{}\" doesn't need a mutable reference", name)); + &format!("The function/method `{}` doesn't need a mutable reference", name)); } }, _ => (), diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index daf1f6ec12c3..085067935a09 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -3,7 +3,7 @@ //! This lint is **warn** by default use rustc::lint::{LintPass, LintArray, LateLintPass, LateContext}; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc::hir::Expr; use syntax::ast; use utils::{match_type, paths, span_lint}; @@ -59,12 +59,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { let ty = cx.tables.expr_ty(expr); if let ty::TyAdt(_, subst) = ty.sty { if match_type(cx, ty, &paths::MUTEX) { - let mutex_param = &subst.type_at(0).sty; + let mutex_param = subst.type_at(0); if let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = format!("Consider using an {} instead of a Mutex here. If you just want the locking \ behaviour and not the internal type, consider using Mutex<()>.", atomic_name); - match *mutex_param { + match mutex_param.sty { ty::TyUint(t) if t != ast::UintTy::Us => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), ty::TyInt(t) if t != ast::IntTy::Is => span_lint(cx, MUTEX_INTEGER, expr.span, &msg), _ => span_lint(cx, MUTEX_ATOMIC, expr.span, &msg), @@ -75,8 +75,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic { } } -fn get_atomic_name(ty: &ty::TypeVariants) -> Option<(&'static str)> { - match *ty { +fn get_atomic_name(ty: Ty) -> Option<(&'static str)> { + match ty.sty { ty::TyBool => Some("AtomicBool"), ty::TyUint(_) => Some("AtomicUsize"), ty::TyInt(_) => Some("AtomicIsize"), diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index 740dd2bcb3fc..c1965be2c048 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -5,6 +5,7 @@ use rustc::lint::*; use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode}; use rustc::ty; +use rustc::ty::adjustment::{Adjustment, Adjust}; use utils::{span_lint, in_macro}; /// **What it does:** Checks for address of operations (`&`) that are going to @@ -41,9 +42,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow { } if let ExprAddrOf(MutImmutable, ref inner) = e.node { if let ty::TyRef(..) = cx.tables.expr_ty(inner).sty { - if let Some(&ty::adjustment::Adjust::DerefRef { autoderefs, autoref, .. }) = - cx.tables.adjustments.get(&e.id).map(|a| &a.kind) { - if autoderefs > 1 && autoref.is_some() { + for adj3 in cx.tables.expr_adjustments(e).windows(3) { + if let [ + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Borrow(_), .. } + ] = *adj3 { span_lint(cx, NEEDLESS_BORROW, e.span, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 33e9d4a7e574..b8aacb3b4183 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -82,8 +82,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_def_id = cx.tcx.hir.local_def_id(node_id); let preds: Vec = { - let parameter_env = cx.tcx.param_env(fn_def_id); - traits::elaborate_predicates(cx.tcx, parameter_env.caller_bounds.to_vec()) + traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) .filter(|p| !p.is_global()) .collect() }; @@ -91,12 +90,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { // Collect moved variables and spans which will need dereferencings from the function body. let MovedVariablesCtxt { moved_vars, spans_need_deref, .. } = { let mut ctx = MovedVariablesCtxt::new(cx); - let infcx = cx.tcx.borrowck_fake_infer_ctxt(body.id()); let region_maps = &cx.tcx.region_maps(fn_def_id); - { - let mut v = euv::ExprUseVisitor::new(&mut ctx, region_maps, &infcx); - v.consume_body(body); - } + euv::ExprUseVisitor::new(&mut ctx, cx.tcx, cx.param_env, region_maps, cx.tables).consume_body(body); ctx }; @@ -119,9 +114,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if_let_chain! {[ !is_self(arg), !ty.is_mutable_pointer(), - !is_copy(cx, ty, fn_def_id), - !implements_trait(cx, ty, fn_trait, &[], Some(node_id)), - !implements_trait(cx, ty, asref_trait, &[], Some(node_id)), + !is_copy(cx, ty), + !implements_trait(cx, ty, fn_trait, &[]), + !implements_trait(cx, ty, asref_trait, &[]), !implements_borrow_trait, let PatKind::Binding(mode, defid, ..) = arg.pat.node, @@ -190,7 +185,7 @@ struct MovedVariablesCtxt<'a, 'tcx: 'a> { spans_need_deref: HashMap>, } -impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> { +impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { fn new(cx: &'a LateContext<'a, 'tcx>) -> Self { MovedVariablesCtxt { cx: cx, @@ -262,7 +257,7 @@ impl<'a, 'tcx: 'a> MovedVariablesCtxt<'a, 'tcx> { } } -impl<'a, 'tcx: 'a> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { +impl<'a, 'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt<'a, 'tcx> { fn consume(&mut self, consume_id: NodeId, consume_span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move(_) = mode { self.move_common(consume_id, consume_span, cmt); diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 532b0cee8ad3..da6f635e34ef 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,5 +1,5 @@ use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::ty::TyAdt; +use rustc::ty; use rustc::hir::{Expr, ExprStruct}; use utils::span_lint; @@ -34,7 +34,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { let ty = cx.tables.expr_ty(expr); - if let TyAdt(def, _) = ty.sty { + if let ty::TyAdt(def, _) = ty.sty { if fields.len() == def.struct_variant().fields.len() { span_lint(cx, NEEDLESS_UPDATE, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 0abb639d59a1..34f467184f3b 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -2,7 +2,7 @@ use rustc::hir::intravisit::FnKind; use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint::*; -use rustc::ty; +use rustc::ty::{self, Ty}; use syntax::ast; use syntax::codemap::Span; use utils::paths; @@ -108,15 +108,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // can't be implemented by default return; } - let def_id = cx.tcx.hir.local_def_id(id); if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_ty = cx.tcx .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); if_let_chain!{[ - self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics - same_tys(cx, self_ty, return_ty(cx, id), def_id), + same_tys(cx, self_ty, return_ty(cx, id)), let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT), - !implements_trait(cx, self_ty, default_trait_id, &[], None) + !implements_trait(cx, self_ty, default_trait_id, &[]) ], { if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { span_lint_and_then(cx, @@ -152,16 +150,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } } -fn can_derive_default<'t, 'c>(ty: ty::Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option { +fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option { match ty.sty { ty::TyAdt(adt_def, substs) if adt_def.is_struct() => { for field in adt_def.all_fields() { let f_ty = field.ty(cx.tcx, substs); - if !implements_trait(cx, f_ty, default_trait_id, &[], None) { + if !implements_trait(cx, f_ty, default_trait_id, &[]) { return None; } } - cx.tcx.hir.span_if_local(adt_def.did) + Some(cx.tcx.def_span(adt_def.did)) }, _ => None, } diff --git a/clippy_lints/src/should_assert_eq.rs b/clippy_lints/src/should_assert_eq.rs index 93baab863472..ea79a77877a0 100644 --- a/clippy_lints/src/should_assert_eq.rs +++ b/clippy_lints/src/should_assert_eq.rs @@ -49,10 +49,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq { let ty1 = cx.tables.expr_ty(expr1); let ty2 = cx.tables.expr_ty(expr2); - let parent = cx.tcx.hir.get_parent(e.id); - - if implements_trait(cx, ty1, debug_trait, &[], Some(parent)) && - implements_trait(cx, ty2, debug_trait, &[], Some(parent)) { + if implements_trait(cx, ty1, debug_trait, &[]) && + implements_trait(cx, ty2, debug_trait, &[]) { span_lint(cx, SHOULD_ASSERT_EQ, e.span, &format!("use `{}{}` for better reporting", debug, sugg)); } }} diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 2aef04e84c6e..1d67e06f8118 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -1,6 +1,5 @@ use rustc::lint::*; -use rustc::ty::TypeVariants::{TyRawPtr, TyRef}; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc::hir::*; use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment}; use utils::sugg; @@ -101,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { e.span, &format!("transmute from a type (`{}`) to itself", from_ty)) }, - (&TyRef(_, rty), &TyRawPtr(ptr_ty)) => { + (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => { span_lint_and_then(cx, USELESS_TRANSMUTE, e.span, @@ -116,8 +115,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { db.span_suggestion(e.span, "try", sugg.to_string()); }) }, - (&ty::TyInt(_), &TyRawPtr(_)) | - (&ty::TyUint(_), &TyRawPtr(_)) => { + (&ty::TyInt(_), &ty::TyRawPtr(_)) | + (&ty::TyUint(_), &ty::TyRawPtr(_)) => { span_lint_and_then(cx, USELESS_TRANSMUTE, e.span, @@ -128,16 +127,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { arg.as_ty(&to_ty.to_string()).to_string()); }) }, - (&ty::TyFloat(_), &TyRef(..)) | - (&ty::TyFloat(_), &TyRawPtr(_)) | - (&ty::TyChar, &TyRef(..)) | - (&ty::TyChar, &TyRawPtr(_)) => { + (&ty::TyFloat(_), &ty::TyRef(..)) | + (&ty::TyFloat(_), &ty::TyRawPtr(_)) | + (&ty::TyChar, &ty::TyRef(..)) | + (&ty::TyChar, &ty::TyRawPtr(_)) => { span_lint(cx, WRONG_TRANSMUTE, e.span, &format!("transmute from a `{}` to a pointer", from_ty)) }, - (&TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => { + (&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => { span_lint(cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -145,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { from_ty, to_ty)) }, - (_, &TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => { + (_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => { span_lint(cx, CROSSPOINTER_TRANSMUTE, e.span, @@ -153,7 +152,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute { from_ty, to_ty)) }, - (&TyRawPtr(from_pty), &TyRef(_, to_rty)) => { + (&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => { span_lint_and_then(cx, TRANSMUTE_PTR_TO_REF, e.span, @@ -189,7 +188,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> 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: &QPath, to_rty: ty::Ty) -> String { +fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: Ty) -> String { let seg = last_path_segment(path); if_let_chain!{[ let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index bdedd5a93bd3..f608c7808a0b 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1,8 +1,9 @@ use reexport::*; +use rustc::hir; use rustc::hir::*; use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap}; use rustc::lint::*; -use rustc::ty; +use rustc::ty::{self, Ty}; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; use syntax::attr::IntType; @@ -106,7 +107,7 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) { } } -fn check_ty(cx: &LateContext, ast_ty: &Ty) { +fn check_ty(cx: &LateContext, ast_ty: &hir::Ty) { if in_macro(ast_ty.span) { return; } @@ -196,8 +197,7 @@ declare_lint! { fn check_let_unit(cx: &LateContext, decl: &Decl) { if let DeclLocal(ref local) = decl.node { - let bindtype = &cx.tables.pat_ty(&local.pat).sty; - match *bindtype { + match cx.tables.pat_ty(&local.pat).sty { ty::TyTuple(slice, _) if slice.is_empty() => { if in_external_macro(cx, decl.span) || in_macro(local.pat.span) { return; @@ -267,8 +267,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp { if let ExprBinary(ref cmp, ref left, _) = expr.node { let op = cmp.node; if op.is_comparison() { - let sty = &cx.tables.expr_ty(left).sty; - match *sty { + match cx.tables.expr_ty(left).sty { ty::TyTuple(slice, _) if slice.is_empty() => { let result = match op { BiEq | BiLe | BiGe => "true", @@ -398,7 +397,7 @@ declare_lint! { /// Returns the size in bits of an integral type. /// Will return 0 if the type is not an int or uint variant -fn int_ty_to_nbits(typ: &ty::TyS) -> usize { +fn int_ty_to_nbits(typ: Ty) -> usize { let n = match typ.sty { ty::TyInt(i) => 4 << (i as usize), ty::TyUint(u) => 4 << (u as usize), @@ -412,7 +411,7 @@ fn int_ty_to_nbits(typ: &ty::TyS) -> usize { } } -fn is_isize_or_usize(typ: &ty::TyS) -> bool { +fn is_isize_or_usize(typ: Ty) -> bool { match typ.sty { ty::TyInt(IntTy::Is) | ty::TyUint(UintTy::Us) => true, @@ -420,7 +419,7 @@ fn is_isize_or_usize(typ: &ty::TyS) -> bool { } } -fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to_f64: bool) { +fn span_precision_loss_lint(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to_f64: bool) { let mantissa_nbits = if cast_to_f64 { 52 } else { 23 }; let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64; let arch_dependent_str = "on targets with 64-bit wide pointers "; @@ -453,7 +452,7 @@ enum ArchSuffix { None, } -fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: &ty::TyS, cast_to: &ty::TyS) { +fn check_truncation_and_wrapping(cx: &LateContext, expr: &Expr, cast_from: Ty, cast_to: Ty) { let arch_64_suffix = " on targets with 64-bit wide pointers"; let arch_32_suffix = " on targets with 32-bit wide pointers"; let cast_unsigned_to_signed = !cast_from.is_signed() && cast_to.is_signed(); @@ -693,7 +692,7 @@ impl<'a, 'tcx> TypeComplexityPass { } } - fn check_type(&self, cx: &LateContext, ty: &Ty) { + fn check_type(&self, cx: &LateContext, ty: &hir::Ty) { if in_macro(ty.span) { return; } @@ -724,7 +723,7 @@ struct TypeComplexityVisitor { } impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { - fn visit_ty(&mut self, ty: &'tcx Ty) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty) { let (add_score, sub_nest) = match ty.node { // _, &x and *x have only small overhead; don't mess with nesting level TyInfer | TyPtr(..) | TyRptr(..) => (1, 0), @@ -909,9 +908,9 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option (), _ => return None, }; @@ -921,7 +920,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option return None, }; - let which = match (ty, cv) { + let which = match (&ty.sty, cv) { (&ty::TyBool, Bool(false)) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | (&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) | @@ -1070,7 +1069,6 @@ impl Ord for FullInt { fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(FullInt, FullInt)> { - use rustc::ty::TypeVariants::{TyInt, TyUint}; use syntax::ast::{IntTy, UintTy}; use std::*; @@ -1082,7 +1080,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( return None; } match pre_cast_ty.sty { - TyInt(int_ty) => { + ty::TyInt(int_ty) => { Some(match int_ty { 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)), @@ -1092,7 +1090,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( IntTy::Is => (FullInt::S(isize::min_value() as i128), FullInt::S(isize::max_value() as i128)), }) }, - TyUint(uint_ty) => { + ty::TyUint(uint_ty) => { Some(match uint_ty { 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)), @@ -1109,6 +1107,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( } } +#[allow(cast_possible_wrap)] fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { use rustc::middle::const_val::ConstVal::*; use rustc_const_eval::ConstContext; @@ -1117,7 +1116,7 @@ fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { Ok(val) => { if let Integral(const_int) = val { match const_int.int_type() { - IntType::SignedInt(_) => #[allow(cast_possible_wrap)] Some(FullInt::S(const_int.to_u128_unchecked() as i128)), + IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)), IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), } } else { diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index c8ceb6be0cc0..1f19e4548572 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount { hir::ExprMatch(ref res, _, _) if is_try(expr).is_some() => { if let hir::ExprCall(ref func, ref args) = res.node { if let hir::ExprPath(ref path) = func.node { - if match_path(path, &paths::CARRIER_TRANSLATE) && args.len() == 1 { + if match_path(path, &paths::TRY_INTO_RESULT) && args.len() == 1 { check_method_call(cx, &args[0], expr); } } diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index 494182ae545b..7c7b3b57a114 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -76,8 +76,7 @@ pub fn range(expr: &hir::Expr) -> Option { end: None, limits: ast::RangeLimits::HalfOpen, }) - } else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || - match_path(path, &paths::RANGE_INCLUSIVE) { + } else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || match_path(path, &paths::RANGE_INCLUSIVE) { Some(Range { start: get_field("start", fields), end: get_field("end", fields), @@ -125,20 +124,17 @@ pub fn is_from_for_desugar(decl: &hir::Decl) -> bool { /// `for pat in arg { body }` becomes `(pat, arg, body)`. pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> { if_let_chain! {[ - let hir::ExprMatch(ref iterexpr, ref arms, _) = expr.node, + let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node, let hir::ExprCall(_, ref iterargs) = iterexpr.node, iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(), let hir::ExprLoop(ref block, _, _) = arms[0].body.node, - block.stmts.is_empty(), - let Some(ref loopexpr) = block.expr, - let hir::ExprMatch(_, ref innerarms, hir::MatchSource::ForLoopDesugar) = loopexpr.node, - innerarms.len() == 2 && innerarms[0].pats.len() == 1, - let hir::PatKind::TupleStruct(_, ref somepats, _) = innerarms[0].pats[0].node, - somepats.len() == 1 + block.expr.is_none(), + let [ ref let_stmt, ref body ] = *block.stmts, + let hir::StmtDecl(ref decl, _) = let_stmt.node, + let hir::DeclLocal(ref decl) = decl.node, + let hir::StmtExpr(ref expr, _) = body.node, ], { - return Some((&somepats[0], - &iterargs[0], - &innerarms[0].body)); + return Some((&*decl.pat, &iterargs[0], expr)); }} None } diff --git a/clippy_lints/src/utils/hir.rs b/clippy_lints/src/utils/hir_utils.rs similarity index 100% rename from clippy_lints/src/utils/hir.rs rename to clippy_lints/src/utils/hir_utils.rs diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index f5f1fe030f40..c2cbd4d4cd03 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -1,15 +1,13 @@ use reexport::*; +use rustc::hir; 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; -use rustc::traits::Reveal; use rustc::traits; -use rustc::ty::subst::{Subst, Substs}; -use rustc::ty; -use rustc::ty::layout::TargetDataLayout; +use rustc::ty::{self, TyCtxt, Ty}; use rustc::mir::transform::MirSource; use rustc_errors; use std::borrow::Cow; @@ -26,12 +24,12 @@ use syntax::symbol::keywords; pub mod comparisons; pub mod conf; pub mod constants; -mod hir; +mod hir_utils; pub mod paths; pub mod sugg; pub mod inspector; pub mod internal_lints; -pub use self::hir::{SpanlessEq, SpanlessHash}; +pub use self::hir_utils::{SpanlessEq, SpanlessHash}; pub type MethodArgs = HirVec>; @@ -149,7 +147,7 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool { /// ``` /// /// See also the `paths` module. -pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool { +pub fn match_def_path(tcx: TyCtxt, def_id: DefId, path: &[&str]) -> bool { use syntax::symbol; struct AbsolutePathBuffer { @@ -175,7 +173,7 @@ pub fn match_def_path(tcx: ty::TyCtxt, def_id: DefId, path: &[&str]) -> bool { } /// Check if type is struct, enum or union type with given def path. -pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { +pub fn match_type(cx: &LateContext, ty: Ty, path: &[&str]) -> bool { match ty.sty { ty::TyAdt(adt, _) => match_def_path(cx.tcx, adt.did, path), _ => false, @@ -184,12 +182,8 @@ pub fn match_type(cx: &LateContext, ty: ty::Ty, path: &[&str]) -> bool { /// Check if the method call given in `expr` belongs to given type. pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tables - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.impl_of_method(callee.def_id)); + let method_call = cx.tables.type_dependent_defs[&expr.id]; + let trt_id = cx.tcx.impl_of_method(method_call.def_id()); if let Some(trt_id) = trt_id { match_def_path(cx.tcx, trt_id, path) } else { @@ -199,12 +193,8 @@ pub fn match_impl_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { /// Check if the method call given in `expr` belongs to given trait. pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool { - let method_call = ty::MethodCall::expr(expr.id); - - let trt_id = cx.tables - .method_map - .get(&method_call) - .and_then(|callee| cx.tcx.trait_of_item(callee.def_id)); + let method_call = cx.tables.type_dependent_defs[&expr.id]; + let trt_id = cx.tcx.trait_of_item(method_call.def_id()); if let Some(trt_id) = trt_id { match_def_path(cx.tcx, trt_id, path) } else { @@ -267,7 +257,6 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool { } /// Get the definition associated to a path. -/// TODO: investigate if there is something more efficient for that. pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { let cstore = &cx.tcx.sess.cstore; @@ -278,7 +267,7 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { krate: *krate, index: CRATE_DEF_INDEX, }; - let mut items = cstore.item_children(krate); + let mut items = cstore.item_children(krate, cx.tcx.sess); let mut path_it = path.iter().skip(1).peekable(); loop { @@ -293,7 +282,7 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option { return Some(item.def); } - items = cstore.item_children(item.def.def_id()); + items = cstore.item_children(item.def.def_id(), cx.tcx.sess); break; } } @@ -320,22 +309,16 @@ pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option { /// See also `get_trait_def_id`. pub fn implements_trait<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, - ty: ty::Ty<'tcx>, + ty: Ty<'tcx>, trait_id: DefId, - ty_params: &[ty::Ty<'tcx>], - parent_node_id: Option + ty_params: &[Ty<'tcx>] ) -> bool { let ty = cx.tcx.erase_regions(&ty); - let mut b = if let Some(id) = parent_node_id { - cx.tcx.infer_ctxt(BodyId { node_id: id }, Reveal::All) - } else { - cx.tcx.infer_ctxt((), Reveal::All) - }; - b.enter(|infcx| { - let obligation = cx.tcx.predicate_for_trait_def(traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); - - traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation) - }) + let obligation = cx.tcx + .predicate_for_trait_def(cx.param_env, traits::ObligationCause::dummy(), trait_id, 0, ty, ty_params); + cx.tcx + .infer_ctxt() + .enter(|infcx| traits::SelectionContext::new(&infcx).evaluate_obligation_conservatively(&obligation)) } /// Resolve the definition of a node from its `NodeId`. @@ -592,14 +575,21 @@ pub fn span_lint_and_sugg<'a, 'tcx: 'a, T: LintContext<'tcx>>( /// replacement. In human-readable format though, it only appears once before the whole suggestion. pub fn multispan_sugg(db: &mut DiagnosticBuilder, help_msg: String, sugg: Vec<(Span, String)>) { let sugg = rustc_errors::CodeSuggestion { - substitution_parts: sugg.into_iter().map(|(span, sub)| rustc_errors::Substitution { span, substitutions: vec![sub] }).collect(), + substitution_parts: sugg.into_iter() + .map(|(span, sub)| { + rustc_errors::Substitution { + span: span, + substitutions: vec![sub], + } + }) + .collect(), msg: help_msg, }; db.suggestions.push(sugg); } /// Return the base type for references and raw pointers. -pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { +pub fn walk_ptrs_ty(ty: Ty) -> Ty { match ty.sty { ty::TyRef(_, ref tm) => walk_ptrs_ty(tm.ty), _ => ty, @@ -607,8 +597,8 @@ pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty { } /// Return the base type for references and raw pointers, and count reference depth. -pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) { - fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) { +pub fn walk_ptrs_ty_depth(ty: Ty) -> (Ty, usize) { + fn inner(ty: Ty, depth: usize) -> (Ty, usize) { match ty.sty { ty::TyRef(_, ref tm) => inner(tm.ty, depth + 1), _ => (ty, depth), @@ -772,7 +762,7 @@ pub fn camel_case_from(s: &str) -> usize { } /// Convenience function to get the return type of a function -pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::Ty<'tcx> { +pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> Ty<'tcx> { let fn_def_id = cx.tcx.hir.local_def_id(fn_item); let ret_ty = cx.tcx.type_of(fn_def_id).fn_sig().output(); cx.tcx.erase_late_bound_regions(&ret_ty) @@ -781,23 +771,12 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::T /// Check if two types are the same. // FIXME: this works correctly for lifetimes bounds (`for <'a> Foo<'a>` == `for <'b> Foo<'b>` but // not for type parameters. -pub fn same_tys<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - a: ty::Ty<'tcx>, - b: ty::Ty<'tcx>, - parameter_item: DefId -) -> bool { - let parameter_env = cx.tcx.param_env(parameter_item); - cx.tcx.infer_ctxt(parameter_env, Reveal::All).enter(|infcx| { - let substs = Substs::identity_for_item(cx.tcx, parameter_item); - let new_a = a.subst(infcx.tcx, substs); - let new_b = b.subst(infcx.tcx, substs); - infcx.can_equate(&new_a, &new_b).is_ok() - }) +pub fn same_tys<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + cx.tcx.infer_ctxt().enter(|infcx| infcx.can_eq(cx.param_env, a, b).is_ok()) } /// Return whether the given type is an `unsafe` function. -pub fn type_is_unsafe_function(ty: ty::Ty) -> bool { +pub fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { ty::TyFnDef(_, _, f) | ty::TyFnPtr(f) => f.unsafety() == Unsafety::Unsafe, @@ -805,10 +784,8 @@ pub fn type_is_unsafe_function(ty: ty::Ty) -> bool { } } -pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, env: DefId) -> bool { - let substs = Substs::identity_for_item(cx.tcx, env); - let env = cx.tcx.param_env(env); - !ty.subst(cx.tcx, substs).moves_by_default(cx.tcx.global_tcx(), env, DUMMY_SP) +pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { + !ty.moves_by_default(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) } /// Return whether a pattern is refutable. @@ -910,7 +887,7 @@ pub fn is_self(slf: &Arg) -> bool { } } -pub fn is_self_ty(slf: &Ty) -> bool { +pub fn is_self_ty(slf: &hir::Ty) -> bool { if_let_chain! {[ let TyPath(ref qp) = slf.node, let QPath::Resolved(None, ref path) = *qp, @@ -969,8 +946,6 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { None } -pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>) -> Option { - cx.tcx - .infer_ctxt((), Reveal::All) - .enter(|infcx| ty.layout(&infcx).ok().map(|lay| lay.size(&TargetDataLayout::parse(cx.sess())).bytes())) +pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option { + ty.layout(cx.tcx, cx.param_env).ok().map(|layout| layout.size(cx.tcx).bytes()) } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 133a2d65f0e3..eb9979343948 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,5 +1,6 @@ //! This module contains paths to types and functions Clippy needs to know about. +pub const ASMUT_TRAIT: [&'static str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&'static str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&'static str; 3] = ["std", "panicking", "begin_panic"]; pub const BINARY_HEAP: [&'static str; 3] = ["collections", "binary_heap", "BinaryHeap"]; @@ -9,7 +10,6 @@ pub const BOX_NEW: [&'static str; 4] = ["std", "boxed", "Box", "new"]; pub const BTREEMAP: [&'static str; 4] = ["collections", "btree", "map", "BTreeMap"]; pub const BTREEMAP_ENTRY: [&'static str; 4] = ["collections", "btree", "map", "Entry"]; pub const BTREESET: [&'static str; 4] = ["collections", "btree", "set", "BTreeSet"]; -pub const CARRIER_TRANSLATE: [&'static str; 4] = ["std", "ops", "Carrier", "translate"]; pub const CLONE: [&'static str; 4] = ["core", "clone", "Clone", "clone"]; pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"]; pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"]; @@ -72,6 +72,7 @@ pub const STRING: [&'static str; 3] = ["collections", "string", "String"]; pub const TO_OWNED: [&'static str; 3] = ["collections", "borrow", "ToOwned"]; pub const TO_STRING: [&'static str; 3] = ["collections", "string", "ToString"]; pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"]; +pub const TRY_INTO_RESULT: [&'static str; 4] = ["std", "ops", "Try", "into_result"]; pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"]; pub const VEC_DEQUE: [&'static str; 3] = ["collections", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&'static str; 3] = ["collections", "vec", "from_elem"]; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index e162406b8dc3..3c672b22ee60 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,6 +1,6 @@ use rustc::hir::*; use rustc::lint::*; -use rustc::ty; +use rustc::ty::{self, Ty}; use rustc_const_eval::ConstContext; use syntax::codemap::Span; use utils::{higher, is_copy, snippet, span_lint_and_then}; @@ -35,8 +35,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { // search for `&vec![_]` expressions where the adjusted type is `&[_]` if_let_chain!{[ - let ty::TypeVariants::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty, - let ty::TypeVariants::TySlice(..) = ty.ty.sty, + let ty::TyRef(_, ref ty) = cx.tables.expr_ty_adjusted(expr).sty, + let ty::TySlice(..) = ty.ty.sty, let ExprAddrOf(_, ref addressee) = expr.node, let Some(vec_args) = higher::vec_macro(cx, addressee), ], { @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if_let_chain!{[ let Some((_, arg, _)) = higher::for_loop(expr), let Some(vec_args) = higher::vec_macro(cx, arg), - is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg)), cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(expr.id))), + is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg))), ], { // report the error around the `vec!` not inside `:` let span = arg.span.ctxt.outer().expn_info().map(|info| info.call_site).expect("unable to get call_site"); @@ -88,7 +88,7 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { } /// Return the item type of the vector (ie. the `T` in `Vec`). -fn vec_type(ty: ty::Ty) -> ty::Ty { +fn vec_type(ty: Ty) -> Ty { if let ty::TyAdt(_, substs) = ty.sty { substs.type_at(0) } else { diff --git a/clippy_tests/examples/assign_ops.stderr b/clippy_tests/examples/assign_ops.stderr index 0c7d2b3b4931..8e399b90d9d2 100644 --- a/clippy_tests/examples/assign_ops.stderr +++ b/clippy_tests/examples/assign_ops.stderr @@ -166,6 +166,14 @@ error: manual implementation of an assign operation | = note: `-D assign-op-pattern` implied by `-D warnings` +error: manual implementation of an assign operation + --> assign_ops.rs:40:5 + | +40 | s = s + "bla"; + | ^^^^^^^^^^^^^ help: replace it with `s += "bla"` + | + = note: `-D assign-op-pattern` implied by `-D warnings` + error: aborting due to previous error(s) error: Could not compile `clippy_tests`. diff --git a/clippy_tests/examples/for_loop.stderr b/clippy_tests/examples/for_loop.stderr index bd4f1bc8ee5d..e752ffd2362c 100644 --- a/clippy_tests/examples/for_loop.stderr +++ b/clippy_tests/examples/for_loop.stderr @@ -317,6 +317,14 @@ error: this range is empty so this for loop will never run | = note: `-D reverse-range-loop` implied by `-D warnings` +error: use of deprecated item: replaced by `Iterator::step_by` + --> for_loop.rs:192:22 + | +192 | for i in (10..8).step_by(-1) { + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + error: it is more idiomatic to loop over references to containers instead of using explicit iteration methods --> for_loop.rs:207:15 | diff --git a/clippy_tests/examples/mut_reference.stderr b/clippy_tests/examples/mut_reference.stderr index 34d33f622190..c8f606db0e17 100644 --- a/clippy_tests/examples/mut_reference.stderr +++ b/clippy_tests/examples/mut_reference.stderr @@ -1,4 +1,4 @@ -error: The function/method "takes_an_immutable_reference" doesn't need a mutable reference +error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference --> mut_reference.rs:22:34 | 22 | takes_an_immutable_reference(&mut 42); @@ -6,7 +6,7 @@ error: The function/method "takes_an_immutable_reference" doesn't need a mutable | = note: `-D unnecessary-mut-passed` implied by `-D warnings` -error: The function/method "as_ptr" doesn't need a mutable reference +error: The function/method `as_ptr` doesn't need a mutable reference --> mut_reference.rs:24:12 | 24 | as_ptr(&mut 42); @@ -14,7 +14,7 @@ error: The function/method "as_ptr" doesn't need a mutable reference | = note: `-D unnecessary-mut-passed` implied by `-D warnings` -error: The function/method "takes_an_immutable_reference" doesn't need a mutable reference +error: The function/method `takes_an_immutable_reference` doesn't need a mutable reference --> mut_reference.rs:28:44 | 28 | my_struct.takes_an_immutable_reference(&mut 42); diff --git a/clippy_tests/examples/range.stderr b/clippy_tests/examples/range.stderr index 1d23f1425870..2f3aa7971d01 100644 --- a/clippy_tests/examples/range.stderr +++ b/clippy_tests/examples/range.stderr @@ -6,6 +6,22 @@ error: Range::step_by(0) produces an infinite iterator. Consider using `std::ite | = note: `-D range-step-by-zero` implied by `-D warnings` +error: use of deprecated item: replaced by `Iterator::step_by` + --> range.rs:13:12 + | +13 | (0..1).step_by(0); + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + +error: use of deprecated item: replaced by `Iterator::step_by` + --> range.rs:15:12 + | +15 | (0..1).step_by(1); + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + error: Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` instead --> range.rs:17:5 | @@ -14,6 +30,14 @@ error: Range::step_by(0) produces an infinite iterator. Consider using `std::ite | = note: `-D range-step-by-zero` implied by `-D warnings` +error: use of deprecated item: replaced by `Iterator::step_by` + --> range.rs:17:11 + | +17 | (1..).step_by(0); + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + error: Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` instead --> range.rs:18:5 | @@ -22,6 +46,14 @@ error: Range::step_by(0) produces an infinite iterator. Consider using `std::ite | = note: `-D range-step-by-zero` implied by `-D warnings` +error: use of deprecated item: replaced by `Iterator::step_by` + --> range.rs:18:13 + | +18 | (1...2).step_by(0); + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + error: Range::step_by(0) produces an infinite iterator. Consider using `std::iter::repeat()` instead --> range.rs:21:5 | @@ -30,6 +62,14 @@ error: Range::step_by(0) produces an infinite iterator. Consider using `std::ite | = note: `-D range-step-by-zero` implied by `-D warnings` +error: use of deprecated item: replaced by `Iterator::step_by` + --> range.rs:21:7 + | +21 | x.step_by(0); + | ^^^^^^^ + | + = note: `-D deprecated` implied by `-D warnings` + error: It is more idiomatic to use v1.iter().enumerate() --> range.rs:29:14 | diff --git a/clippy_tests/examples/strings.stderr b/clippy_tests/examples/strings.stderr index a12346086d3a..2b0e4dcdf1b3 100644 --- a/clippy_tests/examples/strings.stderr +++ b/clippy_tests/examples/strings.stderr @@ -1,3 +1,11 @@ +error: manual implementation of an assign operation + --> strings.rs:10:9 + | +10 | x = x + "."; + | ^^^^^^^^^^^ help: replace it with `x += "."` + | + = note: `-D assign-op-pattern` implied by `-D warnings` + error: you added something to a string. Consider using `String::push_str()` instead --> strings.rs:10:13 | @@ -22,6 +30,14 @@ error: you assigned the result of adding something to this string. Consider usin | = note: `-D string-add-assign` implied by `-D warnings` +error: manual implementation of an assign operation + --> strings.rs:24:9 + | +24 | x = x + "."; + | ^^^^^^^^^^^ help: replace it with `x += "."` + | + = note: `-D assign-op-pattern` implied by `-D warnings` + error: you assigned the result of adding something to this string. Consider using `String::push_str()` instead --> strings.rs:38:9 | @@ -30,6 +46,14 @@ error: you assigned the result of adding something to this string. Consider usin | = note: `-D string-add-assign` implied by `-D warnings` +error: manual implementation of an assign operation + --> strings.rs:38:9 + | +38 | x = x + "."; + | ^^^^^^^^^^^ help: replace it with `x += "."` + | + = note: `-D assign-op-pattern` implied by `-D warnings` + error: you added something to a string. Consider using `String::push_str()` instead --> strings.rs:42:13 | diff --git a/clippy_tests/examples/wrong_self_convention.rs b/clippy_tests/examples/wrong_self_convention.rs index 0fbe4eff6d6c..91b60c8faaa2 100644 --- a/clippy_tests/examples/wrong_self_convention.rs +++ b/clippy_tests/examples/wrong_self_convention.rs @@ -29,6 +29,8 @@ impl Foo { #[allow(wrong_self_convention)] pub fn from_cake(self) {} + fn as_x>(_: F) { } + fn as_y>(_: F) { } } struct Bar; diff --git a/clippy_tests/examples/wrong_self_convention.stderr b/clippy_tests/examples/wrong_self_convention.stderr index 7a96ed71024a..91ed88dd4afa 100644 --- a/clippy_tests/examples/wrong_self_convention.stderr +++ b/clippy_tests/examples/wrong_self_convention.stderr @@ -15,81 +15,81 @@ error: methods called `from_*` usually take no self; consider choosing a less am = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> wrong_self_convention.rs:38:15 + --> wrong_self_convention.rs:40:15 | -38 | fn as_i32(self) {} +40 | fn as_i32(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> wrong_self_convention.rs:40:17 + --> wrong_self_convention.rs:42:17 | -40 | fn into_i32(&self) {} +42 | fn into_i32(&self) {} | ^^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> wrong_self_convention.rs:42:15 + --> wrong_self_convention.rs:44:15 | -42 | fn is_i32(self) {} +44 | fn is_i32(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> wrong_self_convention.rs:44:15 + --> wrong_self_convention.rs:46:15 | -44 | fn to_i32(self) {} +46 | fn to_i32(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> wrong_self_convention.rs:46:17 + --> wrong_self_convention.rs:48:17 | -46 | fn from_i32(self) {} +48 | fn from_i32(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `as_*` usually take self by reference or self by mutable reference; consider choosing a less ambiguous name - --> wrong_self_convention.rs:48:19 + --> wrong_self_convention.rs:50:19 | -48 | pub fn as_i64(self) {} +50 | pub fn as_i64(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> wrong_self_convention.rs:49:21 + --> wrong_self_convention.rs:51:21 | -49 | pub fn into_i64(&self) {} +51 | pub fn into_i64(&self) {} | ^^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `is_*` usually take self by reference or no self; consider choosing a less ambiguous name - --> wrong_self_convention.rs:50:19 + --> wrong_self_convention.rs:52:19 | -50 | pub fn is_i64(self) {} +52 | pub fn is_i64(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> wrong_self_convention.rs:51:19 + --> wrong_self_convention.rs:53:19 | -51 | pub fn to_i64(self) {} +53 | pub fn to_i64(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings` error: methods called `from_*` usually take no self; consider choosing a less ambiguous name - --> wrong_self_convention.rs:52:21 + --> wrong_self_convention.rs:54:21 | -52 | pub fn from_i64(self) {} +54 | pub fn from_i64(self) {} | ^^^^ | = note: `-D wrong-self-convention` implied by `-D warnings`