mirror of
https://github.com/rust-lang/rust-clippy
synced 2025-02-17 06:28:42 +00:00
Rustup to rustc 1.15.0-nightly (0ed951993 2016-11-14)
This commit is contained in:
parent
bad26a5aca
commit
19c5f5394b
53 changed files with 237 additions and 246 deletions
|
@ -59,7 +59,7 @@ impl LateLintPass for Arithmetic {
|
|||
hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return,
|
||||
_ => (),
|
||||
}
|
||||
let (l_ty, r_ty) = (cx.tcx.expr_ty(l), cx.tcx.expr_ty(r));
|
||||
let (l_ty, r_ty) = (cx.tcx.tables().expr_ty(l), cx.tcx.tables().expr_ty(r));
|
||||
if l_ty.is_integral() && r_ty.is_integral() {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
|
@ -69,7 +69,7 @@ impl LateLintPass for Arithmetic {
|
|||
}
|
||||
}
|
||||
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
|
||||
let ty = cx.tcx.expr_ty(arg);
|
||||
let ty = cx.tcx.tables().expr_ty(arg);
|
||||
if ty.is_integral() {
|
||||
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
|
||||
self.span = Some(expr.span);
|
||||
|
|
|
@ -59,7 +59,7 @@ impl LateLintPass for ArrayIndexing {
|
|||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
||||
if let hir::ExprIndex(ref array, ref index) = e.node {
|
||||
// Array with known size can be checked statically
|
||||
let ty = cx.tcx.expr_ty(array);
|
||||
let ty = cx.tcx.tables().expr_ty(array);
|
||||
if let ty::TyArray(_, size) = ty.sty {
|
||||
let size = ConstInt::Infer(size as u64);
|
||||
|
||||
|
|
|
@ -81,11 +81,11 @@ impl LateLintPass 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.tcx.expr_ty(assignee);
|
||||
let ty = cx.tcx.tables().expr_ty(assignee);
|
||||
if ty.walk_shallow().next().is_some() {
|
||||
return; // implements_trait does not work with generics
|
||||
}
|
||||
let rty = cx.tcx.expr_ty(rhs);
|
||||
let rty = cx.tcx.tables().expr_ty(rhs);
|
||||
if rty.walk_shallow().next().is_some() {
|
||||
return; // implements_trait does not work with generics
|
||||
}
|
||||
|
@ -116,11 +116,11 @@ impl LateLintPass for AssignOps {
|
|||
hir::ExprAssign(ref assignee, ref e) => {
|
||||
if let hir::ExprBinary(op, ref l, ref r) = e.node {
|
||||
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
|
||||
let ty = cx.tcx.expr_ty(assignee);
|
||||
let ty = cx.tcx.tables().expr_ty(assignee);
|
||||
if ty.walk_shallow().next().is_some() {
|
||||
return; // implements_trait does not work with generics
|
||||
}
|
||||
let rty = cx.tcx.expr_ty(rhs);
|
||||
let rty = cx.tcx.tables().expr_ty(rhs);
|
||||
if rty.walk_shallow().next().is_some() {
|
||||
return; // implements_trait does not work with generics
|
||||
}
|
||||
|
|
|
@ -152,8 +152,8 @@ impl LateLintPass for AttrPass {
|
|||
}
|
||||
|
||||
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
|
||||
if let ItemFn(_, _, _, _, _, ref block) = item.node {
|
||||
is_relevant_block(cx, block)
|
||||
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
|
||||
is_relevant_expr(cx, expr)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
|
|||
|
||||
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
|
||||
match item.node {
|
||||
ImplItemKind::Method(_, ref block) => is_relevant_block(cx, block),
|
||||
ImplItemKind::Method(_, ref expr) => is_relevant_expr(cx, expr),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
|
|||
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
|
||||
match item.node {
|
||||
MethodTraitItem(_, None) => true,
|
||||
MethodTraitItem(_, Some(ref block)) => is_relevant_block(cx, block),
|
||||
MethodTraitItem(_, Some(ref expr)) => is_relevant_expr(cx, expr),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,17 +55,9 @@ struct ExVisitor<'v> {
|
|||
|
||||
impl<'v> Visitor<'v> for ExVisitor<'v> {
|
||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
||||
if let ExprClosure(_, _, ref block, _) = expr.node {
|
||||
if let ExprClosure(_, _, ref expr, _) = expr.node {
|
||||
let complex = {
|
||||
if block.stmts.is_empty() {
|
||||
if let Some(ref ex) = block.expr {
|
||||
matches!(ex.node, ExprBlock(_))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
matches!(expr.node, ExprBlock(_))
|
||||
};
|
||||
if complex {
|
||||
self.found_block = Some(expr);
|
||||
|
|
|
@ -392,7 +392,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
|
|||
match e.node {
|
||||
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
|
||||
ExprUnary(UnNot, ref inner) => {
|
||||
if self.0.tcx.node_types()[&inner.id].is_bool() {
|
||||
if self.0.tcx.tables.borrow().node_types[&inner.id].is_bool() {
|
||||
self.bool_expr(e);
|
||||
} else {
|
||||
walk_expr(self, e);
|
||||
|
|
|
@ -120,8 +120,8 @@ impl LateLintPass for CopyAndPaste {
|
|||
}
|
||||
|
||||
let (conds, blocks) = if_sequence(expr);
|
||||
lint_same_then_else(cx, blocks.as_slice());
|
||||
lint_same_cond(cx, conds.as_slice());
|
||||
lint_same_then_else(cx, &blocks);
|
||||
lint_same_cond(cx, &conds);
|
||||
lint_match_arms(cx, expr);
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +219,8 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) {
|
|||
/// Eg. would return `([a, b], [c, d, e])` for the expression
|
||||
/// `if a { c } else if b { d } else { e }`.
|
||||
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
|
||||
let mut conds = SmallVector::zero();
|
||||
let mut blocks = SmallVector::zero();
|
||||
let mut conds = SmallVector::new();
|
||||
let mut blocks = SmallVector::new();
|
||||
|
||||
while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
|
||||
conds.push(&**cond);
|
||||
|
@ -256,7 +256,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
|
|||
}
|
||||
PatKind::Binding(_, ref ident, ref as_pat) => {
|
||||
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) {
|
||||
v.insert(cx.tcx.pat_ty(pat));
|
||||
v.insert(cx.tcx.tables().pat_ty(pat));
|
||||
}
|
||||
if let Some(ref as_pat) = *as_pat {
|
||||
bindings_impl(cx, as_pat, map);
|
||||
|
|
|
@ -42,12 +42,12 @@ impl LintPass for CyclomaticComplexity {
|
|||
}
|
||||
|
||||
impl CyclomaticComplexity {
|
||||
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, block: &Block, span: Span) {
|
||||
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &Expr, span: Span) {
|
||||
if in_macro(cx, span) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cfg = CFG::new(cx.tcx, block);
|
||||
let cfg = CFG::new(cx.tcx, expr);
|
||||
let n = cfg.graph.len_nodes() as u64;
|
||||
let e = cfg.graph.len_edges() as u64;
|
||||
if e + 2 < n {
|
||||
|
@ -62,9 +62,9 @@ impl CyclomaticComplexity {
|
|||
returns: 0,
|
||||
tcx: &cx.tcx,
|
||||
};
|
||||
helper.visit_block(block);
|
||||
helper.visit_expr(expr);
|
||||
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
|
||||
let ret_ty = cx.tcx.node_id_to_type(block.id);
|
||||
let ret_ty = cx.tcx.tables().node_id_to_type(expr.id);
|
||||
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
|
||||
returns
|
||||
} else {
|
||||
|
@ -92,22 +92,22 @@ impl CyclomaticComplexity {
|
|||
|
||||
impl LateLintPass for CyclomaticComplexity {
|
||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
||||
if let ItemFn(_, _, _, _, _, ref block) = item.node {
|
||||
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
|
||||
if !attr::contains_name(&item.attrs, "test") {
|
||||
self.check(cx, block, item.span);
|
||||
self.check(cx, expr, item.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
||||
if let ImplItemKind::Method(_, ref block) = item.node {
|
||||
self.check(cx, block, item.span);
|
||||
if let ImplItemKind::Method(_, ref expr) = item.node {
|
||||
self.check(cx, expr, item.span);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
||||
if let MethodTraitItem(_, Some(ref block)) = item.node {
|
||||
self.check(cx, block, item.span);
|
||||
if let MethodTraitItem(_, Some(ref expr)) = item.node {
|
||||
self.check(cx, expr, item.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
|
|||
}
|
||||
ExprCall(ref callee, _) => {
|
||||
walk_expr(self, e);
|
||||
let ty = self.tcx.node_id_to_type(callee.id);
|
||||
let ty = self.tcx.tables().node_id_to_type(callee.id);
|
||||
match ty.sty {
|
||||
ty::TyFnDef(_, _, ty) |
|
||||
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {
|
||||
|
|
|
@ -73,7 +73,7 @@ impl LintPass for Derive {
|
|||
impl LateLintPass for Derive {
|
||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
||||
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
|
||||
let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
|
||||
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
|
||||
let is_automatically_derived = is_automatically_derived(&*item.attrs);
|
||||
|
||||
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);
|
||||
|
|
|
@ -52,7 +52,7 @@ impl LateLintPass for Pass {
|
|||
}
|
||||
|
||||
fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) {
|
||||
let arg_ty = cx.tcx.expr_ty(arg);
|
||||
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
||||
if let ty::TyRef(..) = arg_ty.sty {
|
||||
span_note_and_lint(cx,
|
||||
DROP_REF,
|
||||
|
|
|
@ -86,7 +86,7 @@ fn check_cond<'a, 'tcx, 'b>(cx: &'a LateContext<'a, 'tcx>, check: &'b Expr) -> O
|
|||
let ExprAddrOf(_, ref key) = params[1].node
|
||||
], {
|
||||
let map = ¶ms[0];
|
||||
let obj_ty = walk_ptrs_ty(cx.tcx.expr_ty(map));
|
||||
let obj_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(map));
|
||||
|
||||
return if match_type(cx, obj_ty, &paths::BTREEMAP) {
|
||||
Some(("BTreeMap", map, key))
|
||||
|
|
|
@ -5,7 +5,6 @@ use rustc::infer::InferCtxt;
|
|||
use rustc::lint::*;
|
||||
use rustc::middle::expr_use_visitor::*;
|
||||
use rustc::middle::mem_categorization::{cmt, Categorization};
|
||||
use rustc::ty::adjustment::AutoAdjustment;
|
||||
use rustc::ty;
|
||||
use rustc::ty::layout::TargetDataLayout;
|
||||
use rustc::util::nodemap::NodeSet;
|
||||
|
@ -62,7 +61,7 @@ impl LintPass for Pass {
|
|||
}
|
||||
|
||||
impl LateLintPass for Pass {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Block, _: Span, id: NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Expr, _: Span, id: NodeId) {
|
||||
let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);
|
||||
|
||||
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
|
||||
|
@ -146,17 +145,19 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'g
|
|||
}
|
||||
fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: &ty::Region, _: ty::BorrowKind,
|
||||
loan_cause: LoanCause) {
|
||||
use rustc::ty::adjustment::Adjust;
|
||||
|
||||
if let Categorization::Local(lid) = cmt.cat {
|
||||
if self.set.contains(&lid) {
|
||||
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx
|
||||
if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
|
||||
.tables
|
||||
.borrow()
|
||||
.adjustments
|
||||
.get(&borrow_id) {
|
||||
.get(&borrow_id)
|
||||
.map(|a| &a.kind) {
|
||||
if LoanCause::AutoRef == loan_cause {
|
||||
// x.foo()
|
||||
if adj.autoderefs == 0 {
|
||||
if autoderefs == 0 {
|
||||
self.set.remove(&lid); // Used without autodereffing (i.e. x.clone())
|
||||
}
|
||||
} else {
|
||||
|
@ -164,14 +165,15 @@ impl<'a, 'tcx: 'a+'gcx, 'gcx: 'a> Delegate<'tcx> for EscapeDelegate<'a, 'tcx, 'g
|
|||
}
|
||||
} else if LoanCause::AddrOf == loan_cause {
|
||||
// &x
|
||||
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx
|
||||
if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
|
||||
.tables
|
||||
.borrow()
|
||||
.adjustments
|
||||
.get(&self.tcx
|
||||
.map
|
||||
.get_parent_node(borrow_id)) {
|
||||
if adj.autoderefs <= 1 {
|
||||
.map
|
||||
.get_parent_node(borrow_id))
|
||||
.map(|a| &a.kind) {
|
||||
if autoderefs <= 1 {
|
||||
// foo(&x) where no extra autoreffing is happening
|
||||
self.set.remove(&lid);
|
||||
}
|
||||
|
|
|
@ -48,60 +48,53 @@ impl LateLintPass for EtaPass {
|
|||
}
|
||||
|
||||
fn check_closure(cx: &LateContext, expr: &Expr) {
|
||||
if let ExprClosure(_, ref decl, ref blk, _) = expr.node {
|
||||
if !blk.stmts.is_empty() {
|
||||
// || {foo(); bar()}; can't be reduced here
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ref ex) = blk.expr {
|
||||
if let ExprCall(ref caller, ref args) = ex.node {
|
||||
if args.len() != decl.inputs.len() {
|
||||
// Not the same number of arguments, there
|
||||
// is no way the closure is the same as the function
|
||||
return;
|
||||
if let ExprClosure(_, ref decl, ref ex, _) = expr.node {
|
||||
if let ExprCall(ref caller, ref args) = ex.node {
|
||||
if args.len() != decl.inputs.len() {
|
||||
// Not the same number of arguments, there
|
||||
// is no way the closure is the same as the function
|
||||
return;
|
||||
}
|
||||
if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
|
||||
// Are the expression or the arguments type-adjusted? Then we need the closure
|
||||
return;
|
||||
}
|
||||
let fn_ty = cx.tcx.tables().expr_ty(caller);
|
||||
match fn_ty.sty {
|
||||
// Is it an unsafe function? They don't implement the closure traits
|
||||
ty::TyFnDef(_, _, fn_ty) |
|
||||
ty::TyFnPtr(fn_ty) => {
|
||||
if fn_ty.unsafety == Unsafety::Unsafe ||
|
||||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
|
||||
// Are the expression or the arguments type-adjusted? Then we need the closure
|
||||
return;
|
||||
}
|
||||
let fn_ty = cx.tcx.expr_ty(caller);
|
||||
match fn_ty.sty {
|
||||
// Is it an unsafe function? They don't implement the closure traits
|
||||
ty::TyFnDef(_, _, fn_ty) |
|
||||
ty::TyFnPtr(fn_ty) => {
|
||||
if fn_ty.unsafety == Unsafety::Unsafe ||
|
||||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
|
||||
_ => (),
|
||||
}
|
||||
for (a1, a2) in decl.inputs.iter().zip(args) {
|
||||
if let PatKind::Binding(_, ident, _) = a1.pat.node {
|
||||
// XXXManishearth Should I be checking the binding mode here?
|
||||
if let ExprPath(None, ref p) = a2.node {
|
||||
if p.segments.len() != 1 {
|
||||
// If it's a proper path, it can't be a local variable
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
for (a1, a2) in decl.inputs.iter().zip(args) {
|
||||
if let PatKind::Binding(_, ident, _) = a1.pat.node {
|
||||
// XXXManishearth Should I be checking the binding mode here?
|
||||
if let ExprPath(None, ref p) = a2.node {
|
||||
if p.segments.len() != 1 {
|
||||
// If it's a proper path, it can't be a local variable
|
||||
return;
|
||||
}
|
||||
if p.segments[0].name != ident.node {
|
||||
// The two idents should be the same
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if p.segments[0].name != ident.node {
|
||||
// The two idents should be the same
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
|
||||
if let Some(snippet) = snippet_opt(cx, caller.span) {
|
||||
db.span_suggestion(expr.span, "remove closure as shown:", snippet);
|
||||
}
|
||||
});
|
||||
}
|
||||
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
|
||||
if let Some(snippet) = snippet_opt(cx, caller.span) {
|
||||
db.span_suggestion(expr.span, "remove closure as shown:", snippet);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
|
|||
ExprAgain(_) |
|
||||
ExprBreak(_) |
|
||||
ExprRet(_) => self.report_diverging_sub_expr(e),
|
||||
ExprCall(ref func, _) => match self.0.tcx.expr_ty(func).sty {
|
||||
ExprCall(ref func, _) => match self.0.tcx.tables().expr_ty(func).sty {
|
||||
ty::TyFnDef(_, _, fn_ty) |
|
||||
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty {
|
||||
self.report_diverging_sub_expr(e);
|
||||
|
|
|
@ -132,7 +132,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
|
|||
let Some(fun) = resolve_node(cx, args[1].id),
|
||||
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD),
|
||||
], {
|
||||
let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0]));
|
||||
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));
|
||||
|
||||
return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
|
||||
}}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl LintPass for Functions {
|
|||
}
|
||||
|
||||
impl LateLintPass for Functions {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, expr: &hir::Expr, span: Span, nodeid: ast::NodeId) {
|
||||
use rustc::hir::map::Node::*;
|
||||
|
||||
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
||||
|
@ -94,18 +94,18 @@ impl LateLintPass for Functions {
|
|||
}
|
||||
}
|
||||
|
||||
self.check_raw_ptr(cx, unsafety, decl, block, nodeid);
|
||||
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
|
||||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
|
||||
if let hir::MethodTraitItem(ref sig, ref block) = item.node {
|
||||
if let hir::MethodTraitItem(ref sig, ref expr) = item.node {
|
||||
// don't lint extern functions decls, it's not their fault
|
||||
if sig.abi == Abi::Rust {
|
||||
self.check_arg_number(cx, &sig.decl, item.span);
|
||||
}
|
||||
|
||||
if let Some(ref block) = *block {
|
||||
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.id);
|
||||
if let Some(ref expr) = *expr {
|
||||
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ impl Functions {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, nodeid: ast::NodeId) {
|
||||
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, expr: &hir::Expr, nodeid: ast::NodeId) {
|
||||
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
|
||||
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
|
||||
|
||||
|
@ -132,7 +132,7 @@ impl Functions {
|
|||
ptrs: raw_ptrs,
|
||||
};
|
||||
|
||||
hir::intravisit::walk_block(&mut v, block);
|
||||
hir::intravisit::walk_expr(&mut v, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
|
|||
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
||||
match expr.node {
|
||||
hir::ExprCall(ref f, ref args) => {
|
||||
let ty = self.cx.tcx.expr_ty(f);
|
||||
let ty = self.cx.tcx.tables().expr_ty(f);
|
||||
|
||||
if type_is_unsafe_function(ty) {
|
||||
for arg in args {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc::lint::*;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, ImplOrTraitItem};
|
||||
use rustc::ty;
|
||||
use rustc::hir::*;
|
||||
use syntax::ast::{Lit, LitKind, Name};
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
|
@ -133,7 +133,8 @@ fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) {
|
|||
|
||||
if let Some(i) = impl_items.iter().find(|i| is_named_self(i, "len")) {
|
||||
if cx.access_levels.is_exported(i.id) {
|
||||
let ty = cx.tcx.node_id_to_type(item.id);
|
||||
let def_id = cx.tcx.map.local_def_id(item.id);
|
||||
let ty = cx.tcx.item_type(def_id);
|
||||
|
||||
span_lint(cx,
|
||||
LEN_WITHOUT_IS_EMPTY,
|
||||
|
@ -183,10 +184,15 @@ fn check_len_zero(cx: &LateContext, span: Span, name: &Name, args: &[P<Expr>], l
|
|||
|
||||
/// Check if this type has an `is_empty` method.
|
||||
fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
|
||||
/// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`.
|
||||
fn is_is_empty(item: &ImplOrTraitItem) -> bool {
|
||||
if let ty::MethodTraitItem(ref method) = *item {
|
||||
method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1
|
||||
/// Get an `AssociatedItem` and return true if it matches `is_empty(self)`.
|
||||
fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool {
|
||||
if let ty::AssociatedKind::Method = item.kind {
|
||||
if item.name.as_str() == "is_empty" {
|
||||
let ty = cx.tcx.item_type(item.def_id).fn_sig().skip_binder();
|
||||
ty.inputs.len() == 1
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -195,19 +201,18 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
|
|||
/// Check the inherent impl's items for an `is_empty(self)` method.
|
||||
fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool {
|
||||
cx.tcx.inherent_impls.borrow().get(&id).map_or(false, |impls| impls.iter().any(|imp| {
|
||||
cx.tcx.impl_or_trait_items(*imp).iter().any(|item| {
|
||||
is_is_empty(&cx.tcx.impl_or_trait_item(*item))
|
||||
cx.tcx.associated_items(*imp).any(|item| {
|
||||
is_is_empty(cx, &item)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
let ty = &walk_ptrs_ty(cx.tcx.expr_ty(expr));
|
||||
let ty = &walk_ptrs_ty(cx.tcx.tables().expr_ty(expr));
|
||||
match ty.sty {
|
||||
ty::TyTrait(_) => {
|
||||
cx.tcx
|
||||
.impl_or_trait_items(ty.ty_to_def_id().expect("trait impl not found"))
|
||||
.iter()
|
||||
.any(|item| is_is_empty(&cx.tcx.impl_or_trait_item(*item)))
|
||||
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
|
||||
.any(|item| is_is_empty(cx, &item))
|
||||
}
|
||||
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, id)),
|
||||
ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did),
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
|
|
@ -247,8 +247,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
|||
match def {
|
||||
Def::TyAlias(def_id) |
|
||||
Def::Struct(def_id) => {
|
||||
let type_scheme = self.cx.tcx.lookup_item_type(def_id);
|
||||
for _ in type_scheme.generics.regions.as_slice() {
|
||||
let generics = self.cx.tcx.item_generics(def_id);
|
||||
for _ in generics.regions.as_slice() {
|
||||
self.record(&None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -623,7 +623,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
|
|||
|
||||
/// Check for `for` loops over `Option`s and `Results`
|
||||
fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) {
|
||||
let ty = cx.tcx.expr_ty(arg);
|
||||
let ty = cx.tcx.tables().expr_ty(arg);
|
||||
if match_type(cx, ty, &paths::OPTION) {
|
||||
span_help_and_lint(cx,
|
||||
FOR_LOOP_OVER_OPTION,
|
||||
|
@ -709,7 +709,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
|
|||
_ => (arg.span, arg),
|
||||
};
|
||||
|
||||
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
|
||||
let ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(arg));
|
||||
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) {
|
||||
span_lint_and_then(cx,
|
||||
FOR_KV_MAP,
|
||||
|
@ -854,7 +854,7 @@ impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> {
|
|||
fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
|
||||
// no walk_ptrs_ty: calling iter() on a reference can make sense because it
|
||||
// will allow further borrows afterwards
|
||||
let ty = cx.tcx.expr_ty(e);
|
||||
let ty = cx.tcx.tables().expr_ty(e);
|
||||
is_iterable_array(ty) ||
|
||||
match_type(cx, ty, &paths::VEC) ||
|
||||
match_type(cx, ty, &paths::LINKED_LIST) ||
|
||||
|
|
|
@ -30,11 +30,8 @@ impl LateLintPass for Pass {
|
|||
if let ExprMethodCall(name, _, ref args) = expr.node {
|
||||
if name.node.as_str() == "map" && args.len() == 2 {
|
||||
match args[1].node {
|
||||
ExprClosure(_, ref decl, ref blk, _) => {
|
||||
ExprClosure(_, ref decl, ref closure_expr, _) => {
|
||||
if_let_chain! {[
|
||||
// just one expression in the closure
|
||||
blk.stmts.is_empty(),
|
||||
let Some(ref closure_expr) = blk.expr,
|
||||
// nothing special in the argument, besides reference bindings
|
||||
// (e.g. .map(|&x| x) )
|
||||
let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
|
||||
|
@ -44,7 +41,7 @@ impl LateLintPass for Pass {
|
|||
// 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.pat_ty(&*decl.inputs[0].pat)).1 == 1
|
||||
walk_ptrs_ty_depth(cx.tcx.tables().pat_ty(&*decl.inputs[0].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 \
|
||||
|
@ -101,7 +98,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
|
|||
fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
|
||||
if match_trait_method(cx, expr, &paths::ITERATOR) {
|
||||
Some("iterator")
|
||||
} else if match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(arg)), &paths::OPTION) {
|
||||
} else if match_type(cx, walk_ptrs_ty(cx.tcx.tables().expr_ty(arg)), &paths::OPTION) {
|
||||
Some("Option")
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -159,7 +159,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
|||
// allow match arms with just expressions
|
||||
return;
|
||||
};
|
||||
let ty = cx.tcx.expr_ty(ex);
|
||||
let ty = cx.tcx.tables().expr_ty(ex);
|
||||
if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow {
|
||||
check_single_match_single_pattern(cx, ex, arms, expr, els);
|
||||
check_single_match_opt_like(cx, ex, arms, expr, ty, els);
|
||||
|
@ -243,7 +243,7 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
|
|||
|
||||
fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
||||
// type of expression == bool
|
||||
if cx.tcx.expr_ty(ex).sty == ty::TyBool {
|
||||
if cx.tcx.tables().expr_ty(ex).sty == ty::TyBool {
|
||||
span_lint_and_then(cx,
|
||||
MATCH_BOOL,
|
||||
expr.span,
|
||||
|
@ -296,7 +296,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
|||
}
|
||||
|
||||
fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
|
||||
if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() {
|
||||
if arms.len() >= 2 && cx.tcx.tables().expr_ty(ex).is_integral() {
|
||||
let ranges = all_ranges(cx, arms);
|
||||
let type_ranges = type_ranges(&ranges);
|
||||
if !type_ranges.is_empty() {
|
||||
|
|
|
@ -33,7 +33,7 @@ impl LateLintPass for MemForget {
|
|||
if let ExprPath(None, _) = path_expr.node {
|
||||
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
|
||||
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
|
||||
let forgot_ty = cx.tcx.expr_ty(&args[0]);
|
||||
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);
|
||||
|
||||
if match forgot_ty.ty_adt_def() {
|
||||
Some(def) => def.has_dtor(),
|
||||
|
|
|
@ -573,7 +573,7 @@ impl LateLintPass for Pass {
|
|||
|
||||
lint_or_fun_call(cx, expr, &name.node.as_str(), args);
|
||||
|
||||
let self_ty = cx.tcx.expr_ty_adjusted(&args[0]);
|
||||
let self_ty = cx.tcx.tables().expr_ty_adjusted(&args[0]);
|
||||
if args.len() == 1 && name.node.as_str() == "clone" {
|
||||
lint_clone_on_copy(cx, expr, &args[0], self_ty);
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ impl LateLintPass for Pass {
|
|||
}
|
||||
|
||||
// check conventions w.r.t. conversion method names and predicates
|
||||
let ty = cx.tcx.lookup_item_type(cx.tcx.map.local_def_id(item.id)).ty;
|
||||
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
|
||||
let is_copy = is_copy(cx, ty, item.id);
|
||||
for &(ref conv, self_kinds) in &CONVENTIONS {
|
||||
if_let_chain! {[
|
||||
|
@ -680,7 +680,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
|
|||
.as_str();
|
||||
|
||||
if ["default", "new"].contains(&path) {
|
||||
let arg_ty = cx.tcx.expr_ty(arg);
|
||||
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
||||
let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) {
|
||||
default_trait_id
|
||||
} else {
|
||||
|
@ -724,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
|
|||
"else"),
|
||||
(&paths::RESULT, true, &["or", "unwrap_or"], "else")];
|
||||
|
||||
let self_ty = cx.tcx.expr_ty(self_expr);
|
||||
let self_ty = cx.tcx.tables().expr_ty(self_expr);
|
||||
|
||||
let (fn_has_arguments, poss, suffix) = if let Some(&(_, fn_has_arguments, poss, suffix)) =
|
||||
know_types.iter().find(|&&i| match_type(cx, self_ty, i.0)) {
|
||||
|
@ -762,7 +762,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
|
|||
|
||||
/// Checks for the `CLONE_ON_COPY` lint.
|
||||
fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_ty: ty::Ty) {
|
||||
let ty = cx.tcx.expr_ty(expr);
|
||||
let ty = cx.tcx.tables().expr_ty(expr);
|
||||
let parent = cx.tcx.map.get_parent(expr.id);
|
||||
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent);
|
||||
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty {
|
||||
|
@ -785,7 +785,7 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
|
|||
expr.span,
|
||||
"using `clone` on a `Copy` type",
|
||||
|db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
|
||||
if let ty::TyRef(..) = cx.tcx.expr_ty(arg).sty {
|
||||
if let ty::TyRef(..) = cx.tcx.tables().expr_ty(arg).sty {
|
||||
db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref()));
|
||||
} else {
|
||||
db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip));
|
||||
|
@ -795,11 +795,11 @@ fn lint_clone_on_copy(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr, arg_t
|
|||
}
|
||||
|
||||
fn lint_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0]));
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&args[0]));
|
||||
if !match_type(cx, obj_ty, &paths::VEC) {
|
||||
return;
|
||||
}
|
||||
let arg_ty = cx.tcx.expr_ty(&args[1]);
|
||||
let arg_ty = cx.tcx.tables().expr_ty(&args[1]);
|
||||
if let Some(slice) = derefs_to_slice(cx, &args[1], arg_ty) {
|
||||
span_lint_and_then(cx, EXTEND_FROM_SLICE, expr.span, "use of `extend` to extend a Vec by a slice", |db| {
|
||||
db.span_suggestion(expr.span,
|
||||
|
@ -831,13 +831,13 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
|
|||
// Type of MethodArgs is potentially a Vec
|
||||
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
|
||||
let mut_str = if is_mut { "_mut" } else {""};
|
||||
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tcx.expr_ty(&iter_args[0])).is_some() {
|
||||
let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tcx.tables().expr_ty(&iter_args[0])).is_some() {
|
||||
"slice"
|
||||
}
|
||||
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC) {
|
||||
else if match_type(cx, cx.tcx.tables().expr_ty(&iter_args[0]), &paths::VEC) {
|
||||
"Vec"
|
||||
}
|
||||
else if match_type(cx, cx.tcx.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
|
||||
else if match_type(cx, cx.tcx.tables().expr_ty(&iter_args[0]), &paths::VEC_DEQUE) {
|
||||
"VecDeque"
|
||||
}
|
||||
else {
|
||||
|
@ -856,7 +856,7 @@ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_
|
|||
fn lint_get_unwrap(cx: &LateContext, expr: &hir::Expr, get_args: &MethodArgs, is_mut: bool) {
|
||||
// Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap,
|
||||
// because they do not implement `IndexMut`
|
||||
let expr_ty = cx.tcx.expr_ty(&get_args[0]);
|
||||
let expr_ty = cx.tcx.tables().expr_ty(&get_args[0]);
|
||||
let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
|
||||
"slice"
|
||||
} else if match_type(cx, expr_ty, &paths::VEC) {
|
||||
|
@ -915,7 +915,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option<sug
|
|||
}
|
||||
|
||||
if let hir::ExprMethodCall(name, _, ref args) = expr.node {
|
||||
if &name.node.as_str() == &"iter" && may_slice(cx, cx.tcx.expr_ty(&args[0])) {
|
||||
if &name.node.as_str() == &"iter" && may_slice(cx, cx.tcx.tables().expr_ty(&args[0])) {
|
||||
sugg::Sugg::hir_opt(cx, &*args[0]).map(|sugg| {
|
||||
sugg.addr()
|
||||
})
|
||||
|
@ -942,7 +942,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: ty::Ty) -> Option<sug
|
|||
// Type of MethodArgs is potentially a Vec
|
||||
/// lint use of `unwrap()` for `Option`s and `Result`s
|
||||
fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) {
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&unwrap_args[0]));
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&unwrap_args[0]));
|
||||
|
||||
let mess = if match_type(cx, obj_ty, &paths::OPTION) {
|
||||
Some((OPTION_UNWRAP_USED, "an Option", "None"))
|
||||
|
@ -969,8 +969,8 @@ fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) {
|
|||
/// lint use of `ok().expect()` for `Result`s
|
||||
fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) {
|
||||
// lint if the caller of `ok()` is a `Result`
|
||||
if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) {
|
||||
let result_type = cx.tcx.expr_ty(&ok_args[0]);
|
||||
if match_type(cx, cx.tcx.tables().expr_ty(&ok_args[0]), &paths::RESULT) {
|
||||
let result_type = cx.tcx.tables().expr_ty(&ok_args[0]);
|
||||
if let Some(error_type) = get_error_type(cx, result_type) {
|
||||
if has_debug_impl(error_type, cx) {
|
||||
span_lint(cx,
|
||||
|
@ -987,7 +987,7 @@ fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) {
|
|||
/// lint use of `map().unwrap_or()` for `Option`s
|
||||
fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) {
|
||||
// lint if the caller of `map()` is an `Option`
|
||||
if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) {
|
||||
if match_type(cx, cx.tcx.tables().expr_ty(&map_args[0]), &paths::OPTION) {
|
||||
// lint message
|
||||
let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \
|
||||
`map_or(a, f)` instead";
|
||||
|
@ -1018,7 +1018,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs,
|
|||
/// lint use of `map().unwrap_or_else()` for `Option`s
|
||||
fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &MethodArgs, unwrap_args: &MethodArgs) {
|
||||
// lint if the caller of `map()` is an `Option`
|
||||
if match_type(cx, cx.tcx.expr_ty(&map_args[0]), &paths::OPTION) {
|
||||
if match_type(cx, cx.tcx.tables().expr_ty(&map_args[0]), &paths::OPTION) {
|
||||
// lint message
|
||||
let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \
|
||||
`map_or_else(g, f)` instead";
|
||||
|
@ -1147,7 +1147,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
|
|||
let hir::ExprPath(None, ref path) = fun.node,
|
||||
path.segments.len() == 1 && path.segments[0].name.as_str() == "Some"
|
||||
], {
|
||||
let self_ty = walk_ptrs_ty(cx.tcx.expr_ty_adjusted(&args[0][0]));
|
||||
let self_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty_adjusted(&args[0][0]));
|
||||
|
||||
if self_ty.sty != ty::TyStr {
|
||||
return false;
|
||||
|
|
|
@ -168,7 +168,7 @@ impl LintPass for Pass {
|
|||
}
|
||||
|
||||
impl LateLintPass for Pass {
|
||||
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
|
||||
if let FnKind::Closure(_) = k {
|
||||
// Does not apply to closures
|
||||
return;
|
||||
|
@ -353,14 +353,14 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool {
|
|||
}
|
||||
|
||||
fn is_float(cx: &LateContext, expr: &Expr) -> bool {
|
||||
matches!(walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty, ty::TyFloat(_))
|
||||
matches!(walk_ptrs_ty(cx.tcx.tables().expr_ty(expr)).sty, ty::TyFloat(_))
|
||||
}
|
||||
|
||||
fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) {
|
||||
let (arg_ty, snip) = match expr.node {
|
||||
ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => {
|
||||
if name.as_str() == "to_string" || name.as_str() == "to_owned" && is_str_arg(cx, args) {
|
||||
(cx.tcx.expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
|
||||
(cx.tcx.tables().expr_ty(&args[0]), snippet(cx, args[0].span, ".."))
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
|
|||
ExprCall(ref path, ref v) if v.len() == 1 => {
|
||||
if let ExprPath(None, ref path) = path.node {
|
||||
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) {
|
||||
(cx.tcx.expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
|
||||
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
|
|||
_ => return,
|
||||
};
|
||||
|
||||
let other_ty = cx.tcx.expr_ty(other);
|
||||
let other_ty = cx.tcx.tables().expr_ty(other);
|
||||
let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() {
|
||||
Some(id) => id,
|
||||
None => return,
|
||||
|
@ -413,7 +413,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
|
|||
|
||||
fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool {
|
||||
args.len() == 1 &&
|
||||
matches!(walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty, ty::TyStr)
|
||||
matches!(walk_ptrs_ty(cx.tcx.tables().expr_ty(&args[0])).sty, ty::TyStr)
|
||||
}
|
||||
|
||||
/// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea
|
||||
|
|
|
@ -239,7 +239,7 @@ impl EarlyLintPass for MiscEarly {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
|
||||
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, decl: &FnDecl, _: Span, _: NodeId) {
|
||||
let mut registered_names: HashMap<String, Span> = HashMap::new();
|
||||
|
||||
for arg in &decl.inputs {
|
||||
|
|
|
@ -147,10 +147,7 @@ impl LateLintPass for MissingDoc {
|
|||
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
|
||||
// If the method is an impl for a trait, don't doc.
|
||||
let def_id = cx.tcx.map.local_def_id(impl_item.id);
|
||||
match cx.tcx.impl_or_trait_items.borrow()
|
||||
.get(&def_id)
|
||||
.expect("missing method descriptor?!")
|
||||
.container() {
|
||||
match cx.tcx.associated_item(def_id).container {
|
||||
ty::TraitContainer(_) => return,
|
||||
ty::ImplContainer(cid) => {
|
||||
if cx.tcx.impl_trait_ref(cid).is_some() {
|
||||
|
|
|
@ -65,7 +65,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
|
|||
} else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node {
|
||||
if let hir::ExprAddrOf(hir::MutMutable, _) = e.node {
|
||||
span_lint(self.cx, MUT_MUT, expr.span, "generally you want to avoid `&mut &mut _` if possible");
|
||||
} else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.expr_ty(e).sty {
|
||||
} else if let TyRef(_, TypeAndMut { mutbl: hir::MutMutable, .. }) = self.cx.tcx.tables().expr_ty(e).sty {
|
||||
span_lint(self.cx,
|
||||
MUT_MUT,
|
||||
expr.span,
|
||||
|
|
|
@ -56,7 +56,7 @@ pub struct MutexAtomic;
|
|||
|
||||
impl LateLintPass for MutexAtomic {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
let ty = cx.tcx.expr_ty(expr);
|
||||
let ty = cx.tcx.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;
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
|
||||
use rustc::lint::*;
|
||||
use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode};
|
||||
use rustc::ty::TyRef;
|
||||
use rustc::ty;
|
||||
use utils::{span_lint, in_macro};
|
||||
use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef;
|
||||
|
||||
/// **What it does:** Checks for address of operations (`&`) that are going to
|
||||
/// be dereferenced immediately by the compiler.
|
||||
|
@ -41,9 +40,9 @@ impl LateLintPass for NeedlessBorrow {
|
|||
return;
|
||||
}
|
||||
if let ExprAddrOf(MutImmutable, ref inner) = e.node {
|
||||
if let TyRef(..) = cx.tcx.expr_ty(inner).sty {
|
||||
if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
|
||||
if deref.autoderefs > 1 && deref.autoref.is_some() {
|
||||
if let ty::TyRef(..) = cx.tcx.tables().expr_ty(inner).sty {
|
||||
if let Some(&ty::adjustment::Adjust::DerefRef { autoderefs, autoref, .. }) = cx.tcx.tables.borrow().adjustments.get(&e.id).map(|a| &a.kind) {
|
||||
if autoderefs > 1 && autoref.is_some() {
|
||||
span_lint(cx,
|
||||
NEEDLESS_BORROW,
|
||||
e.span,
|
||||
|
@ -59,9 +58,9 @@ impl LateLintPass for NeedlessBorrow {
|
|||
return;
|
||||
}
|
||||
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node {
|
||||
if let TyRef(_, ref tam) = cx.tcx.pat_ty(pat).sty {
|
||||
if let ty::TyRef(_, ref tam) = cx.tcx.tables().pat_ty(pat).sty {
|
||||
if tam.mutbl == MutImmutable {
|
||||
if let TyRef(..) = tam.ty.sty {
|
||||
if let ty::TyRef(..) = tam.ty.sty {
|
||||
span_lint(cx,
|
||||
NEEDLESS_BORROW,
|
||||
pat.span,
|
||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for Pass {
|
|||
impl LateLintPass for Pass {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
|
||||
let ty = cx.tcx.expr_ty(expr);
|
||||
let ty = cx.tcx.tables().expr_ty(expr);
|
||||
if let TyAdt(def, _) = ty.sty {
|
||||
if fields.len() == def.struct_variant().fields.len() {
|
||||
span_lint(cx,
|
||||
|
|
|
@ -50,7 +50,7 @@ fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
|
|||
let Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
|
||||
let Some(val) = ci.to_u64(),
|
||||
val == 1,
|
||||
cx.tcx.expr_ty(exp).is_integral()
|
||||
cx.tcx.tables().expr_ty(exp).is_integral()
|
||||
], {
|
||||
span_lint(cx,
|
||||
NEG_MULTIPLY,
|
||||
|
|
|
@ -90,7 +90,7 @@ impl LintPass for NewWithoutDefault {
|
|||
}
|
||||
|
||||
impl LateLintPass for NewWithoutDefault {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Expr, span: Span, id: ast::NodeId) {
|
||||
if in_external_macro(cx, span) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,8 +102,7 @@ impl LateLintPass for NewWithoutDefault {
|
|||
}
|
||||
if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) {
|
||||
let self_ty = cx.tcx
|
||||
.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)))
|
||||
.ty;
|
||||
.item_type(cx.tcx.map.local_def_id(cx.tcx.map.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), id),
|
||||
|
|
|
@ -50,7 +50,7 @@ impl LateLintPass for Pass {
|
|||
method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;
|
||||
|
||||
], {
|
||||
let is_result_type = match_type(cx, cx.tcx.expr_ty(&result_types[0]), &paths::RESULT);
|
||||
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 {
|
||||
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,
|
||||
|
|
|
@ -35,7 +35,7 @@ impl LintPass for NonSensical {
|
|||
impl LateLintPass for NonSensical {
|
||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
||||
if let ExprMethodCall(ref name, _, ref arguments) = e.node {
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0]));
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
|
||||
if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
|
||||
let mut options = Vec::new();
|
||||
get_open_options(cx, &arguments[0], &mut options);
|
||||
|
@ -63,7 +63,7 @@ enum OpenOption {
|
|||
|
||||
fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) {
|
||||
if let ExprMethodCall(ref name, _, ref arguments) = argument.node {
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&arguments[0]));
|
||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
|
||||
|
||||
// Only proceed if this is a call on some object of type std::fs::OpenOptions
|
||||
if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {
|
||||
|
|
|
@ -39,8 +39,8 @@ impl LateLintPass for OverflowCheckConditional {
|
|||
let Expr_::ExprPath(_, ref path2) = ident2.node,
|
||||
let Expr_::ExprPath(_, ref path3) = second.node,
|
||||
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
||||
cx.tcx.expr_ty(ident1).is_integral(),
|
||||
cx.tcx.expr_ty(ident2).is_integral()
|
||||
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
||||
cx.tcx.tables().expr_ty(ident2).is_integral()
|
||||
], {
|
||||
if let BinOp_::BiLt = op.node {
|
||||
if let BinOp_::BiAdd = op2.node {
|
||||
|
@ -61,8 +61,8 @@ impl LateLintPass for OverflowCheckConditional {
|
|||
let Expr_::ExprPath(_, ref path2) = ident2.node,
|
||||
let Expr_::ExprPath(_, ref path3) = first.node,
|
||||
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
||||
cx.tcx.expr_ty(ident1).is_integral(),
|
||||
cx.tcx.expr_ty(ident2).is_integral()
|
||||
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
||||
cx.tcx.tables().expr_ty(ident2).is_integral()
|
||||
], {
|
||||
if let BinOp_::BiGt = op.node {
|
||||
if let BinOp_::BiAdd = op2.node {
|
||||
|
|
|
@ -91,7 +91,8 @@ impl LateLintPass for PointerPass {
|
|||
}
|
||||
|
||||
fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
|
||||
let fn_ty = cx.tcx.node_id_to_type(fn_id).fn_sig().skip_binder();
|
||||
let fn_def_id = cx.tcx.map.local_def_id(fn_id);
|
||||
let fn_ty = cx.tcx.item_type(fn_def_id).fn_sig().skip_binder();
|
||||
|
||||
for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) {
|
||||
if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty {
|
||||
|
|
|
@ -89,7 +89,7 @@ impl LateLintPass for StepByZero {
|
|||
fn has_step_by(cx: &LateContext, expr: &Expr) -> bool {
|
||||
// No need for walk_ptrs_ty here because step_by moves self, so it
|
||||
// can't be called on a borrowed range.
|
||||
let ty = cx.tcx.expr_ty(expr);
|
||||
let ty = cx.tcx.tables().expr_ty(expr);
|
||||
|
||||
// Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by
|
||||
match_type(cx, ty, &paths::RANGE)
|
||||
|
|
|
@ -91,7 +91,7 @@ impl LateLintPass for Pass {
|
|||
if_let_chain!{[
|
||||
self.last.is_none(),
|
||||
let Some(ref expr) = block.expr,
|
||||
match_type(cx, cx.tcx.expr_ty(expr), &paths::REGEX),
|
||||
match_type(cx, cx.tcx.tables().expr_ty(expr), &paths::REGEX),
|
||||
let Some(span) = is_expn_of(cx, expr.span, "regex"),
|
||||
], {
|
||||
if !self.spans.contains(&span) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc::lint::*;
|
||||
use syntax::ast::*;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use syntax::visit::FnKind;
|
||||
|
||||
|
@ -45,10 +45,10 @@ pub struct ReturnPass;
|
|||
|
||||
impl ReturnPass {
|
||||
// Check the final stmt or expr in a block for unnecessary return.
|
||||
fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
fn check_block_return(&mut self, cx: &EarlyContext, block: &ast::Block) {
|
||||
if let Some(stmt) = block.stmts.last() {
|
||||
match stmt.node {
|
||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
|
||||
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => {
|
||||
self.check_final_expr(cx, expr, Some(stmt.span));
|
||||
}
|
||||
_ => (),
|
||||
|
@ -57,25 +57,25 @@ impl ReturnPass {
|
|||
}
|
||||
|
||||
// Check a the final expression in a block if it's a return.
|
||||
fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr, span: Option<Span>) {
|
||||
fn check_final_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr, span: Option<Span>) {
|
||||
match expr.node {
|
||||
// simple return is always "bad"
|
||||
ExprKind::Ret(Some(ref inner)) => {
|
||||
ast::ExprKind::Ret(Some(ref inner)) => {
|
||||
self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
|
||||
}
|
||||
// a whole block? check it!
|
||||
ExprKind::Block(ref block) => {
|
||||
ast::ExprKind::Block(ref block) => {
|
||||
self.check_block_return(cx, block);
|
||||
}
|
||||
// an if/if let expr, check both exprs
|
||||
// note, if without else is going to be a type checking error anyways
|
||||
// (except for unit type functions) so we don't match it
|
||||
ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
|
||||
ast::ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
|
||||
self.check_block_return(cx, ifblock);
|
||||
self.check_final_expr(cx, elsexpr, None);
|
||||
}
|
||||
// a match expr, check all arms
|
||||
ExprKind::Match(_, ref arms) => {
|
||||
ast::ExprKind::Match(_, ref arms) => {
|
||||
for arm in arms {
|
||||
self.check_final_expr(cx, &arm.body, Some(arm.body.span));
|
||||
}
|
||||
|
@ -96,18 +96,18 @@ impl ReturnPass {
|
|||
}
|
||||
|
||||
// Check for "let x = EXPR; x"
|
||||
fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
fn check_let_return(&mut self, cx: &EarlyContext, block: &ast::Block) {
|
||||
let mut it = block.stmts.iter();
|
||||
|
||||
// we need both a let-binding stmt and an expr
|
||||
if_let_chain! {[
|
||||
let Some(ref retexpr) = it.next_back(),
|
||||
let StmtKind::Expr(ref retexpr) = retexpr.node,
|
||||
let ast::StmtKind::Expr(ref retexpr) = retexpr.node,
|
||||
let Some(stmt) = it.next_back(),
|
||||
let StmtKind::Local(ref local) = stmt.node,
|
||||
let ast::StmtKind::Local(ref local) = stmt.node,
|
||||
let Some(ref initexpr) = local.init,
|
||||
let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
|
||||
let ExprKind::Path(_, ref path) = retexpr.node,
|
||||
let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
|
||||
let ast::ExprKind::Path(_, ref path) = retexpr.node,
|
||||
match_path_ast(path, &[&id.name.as_str()]),
|
||||
!in_external_macro(cx, initexpr.span),
|
||||
], {
|
||||
|
@ -129,11 +129,14 @@ impl LintPass for ReturnPass {
|
|||
}
|
||||
|
||||
impl EarlyLintPass for ReturnPass {
|
||||
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
|
||||
self.check_block_return(cx, block);
|
||||
fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) {
|
||||
match kind {
|
||||
FnKind::ItemFn(.., block) | FnKind::Method(.., block) => self.check_block_return(cx, block),
|
||||
FnKind::Closure(body) => self.check_final_expr(cx, body, None),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
|
||||
self.check_let_return(cx, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,22 +81,22 @@ impl LintPass for Pass {
|
|||
}
|
||||
|
||||
impl LateLintPass for Pass {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) {
|
||||
if in_external_macro(cx, block.span) {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, expr: &Expr, _: Span, _: NodeId) {
|
||||
if in_external_macro(cx, expr.span) {
|
||||
return;
|
||||
}
|
||||
check_fn(cx, decl, block);
|
||||
check_fn(cx, decl, expr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fn(cx: &LateContext, decl: &FnDecl, block: &Block) {
|
||||
fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
|
||||
let mut bindings = Vec::new();
|
||||
for arg in &decl.inputs {
|
||||
if let PatKind::Binding(_, ident, _) = arg.pat.node {
|
||||
bindings.push((ident.node, ident.span))
|
||||
}
|
||||
}
|
||||
check_block(cx, block, &mut bindings);
|
||||
check_expr(cx, expr, &mut bindings);
|
||||
}
|
||||
|
||||
fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) {
|
||||
|
|
|
@ -114,7 +114,7 @@ impl LateLintPass for StringAdd {
|
|||
}
|
||||
|
||||
fn is_string(cx: &LateContext, e: &Expr) -> bool {
|
||||
match_type(cx, walk_ptrs_ty(cx.tcx.expr_ty(e)), &paths::STRING)
|
||||
match_type(cx, walk_ptrs_ty(cx.tcx.tables().expr_ty(e)), &paths::STRING)
|
||||
}
|
||||
|
||||
fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool {
|
||||
|
|
|
@ -85,7 +85,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
|||
if let ExprIndex(ref lhs1, ref idx1) = lhs1.node {
|
||||
if let ExprIndex(ref lhs2, ref idx2) = lhs2.node {
|
||||
if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) {
|
||||
let ty = walk_ptrs_ty(cx.tcx.expr_ty(lhs1));
|
||||
let ty = walk_ptrs_ty(cx.tcx.tables().expr_ty(lhs1));
|
||||
|
||||
if matches!(ty.sty, ty::TySlice(_)) ||
|
||||
matches!(ty.sty, ty::TyArray(_, _)) ||
|
||||
|
|
|
@ -91,8 +91,8 @@ impl LateLintPass for Transmute {
|
|||
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
|
||||
|
||||
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
|
||||
let from_ty = cx.tcx.expr_ty(&args[0]);
|
||||
let to_ty = cx.tcx.expr_ty(e);
|
||||
let from_ty = cx.tcx.tables().expr_ty(&args[0]);
|
||||
let to_ty = cx.tcx.tables().expr_ty(e);
|
||||
|
||||
match (&from_ty.sty, &to_ty.sty) {
|
||||
_ if from_ty == to_ty => span_lint(
|
||||
|
|
|
@ -126,7 +126,7 @@ declare_lint! {
|
|||
|
||||
fn check_let_unit(cx: &LateContext, decl: &Decl) {
|
||||
if let DeclLocal(ref local) = decl.node {
|
||||
let bindtype = &cx.tcx.pat_ty(&local.pat).sty;
|
||||
let bindtype = &cx.tcx.tables().pat_ty(&local.pat).sty;
|
||||
match *bindtype {
|
||||
ty::TyTuple(slice) if slice.is_empty() => {
|
||||
if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) {
|
||||
|
@ -197,7 +197,7 @@ impl LateLintPass for UnitCmp {
|
|||
if let ExprBinary(ref cmp, ref left, _) = expr.node {
|
||||
let op = cmp.node;
|
||||
if op.is_comparison() {
|
||||
let sty = &cx.tcx.expr_ty(left).sty;
|
||||
let sty = &cx.tcx.tables().expr_ty(left).sty;
|
||||
match *sty {
|
||||
ty::TyTuple(slice) if slice.is_empty() => {
|
||||
let result = match op {
|
||||
|
@ -449,7 +449,7 @@ impl LintPass for CastPass {
|
|||
impl LateLintPass for CastPass {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
if let ExprCast(ref ex, _) = expr.node {
|
||||
let (cast_from, cast_to) = (cx.tcx.expr_ty(ex), cx.tcx.expr_ty(expr));
|
||||
let (cast_from, cast_to) = (cx.tcx.tables().expr_ty(ex), cx.tcx.tables().expr_ty(expr));
|
||||
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
|
||||
match (cast_from.is_integral(), cast_to.is_integral()) {
|
||||
(true, false) => {
|
||||
|
@ -535,7 +535,7 @@ impl LintPass for TypeComplexityPass {
|
|||
}
|
||||
|
||||
impl LateLintPass for TypeComplexityPass {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
|
||||
self.check_fndecl(cx, decl);
|
||||
}
|
||||
|
||||
|
@ -683,7 +683,7 @@ impl LateLintPass for CharLitAsU8 {
|
|||
if let ExprCast(ref e, _) = expr.node {
|
||||
if let ExprLit(ref l) = e.node {
|
||||
if let LitKind::Char(_) = l.node {
|
||||
if ty::TyUint(UintTy::U8) == cx.tcx.expr_ty(expr).sty && !in_macro(cx, expr.span) {
|
||||
if ty::TyUint(UintTy::U8) == cx.tcx.tables().expr_ty(expr).sty && !in_macro(cx, expr.span) {
|
||||
let msg = "casting character literal to u8. `char`s \
|
||||
are 4 bytes wide in rust, so casting to u8 \
|
||||
truncates them";
|
||||
|
@ -791,7 +791,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
|||
use rustc_const_eval::*;
|
||||
use types::ExtremeType::*;
|
||||
|
||||
let ty = &cx.tcx.expr_ty(expr).sty;
|
||||
let ty = &cx.tcx.tables().expr_ty(expr).sty;
|
||||
|
||||
match *ty {
|
||||
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
|
||||
|
@ -953,7 +953,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
|
|||
use std::*;
|
||||
|
||||
if let ExprCast(ref cast_exp, _) = expr.node {
|
||||
match cx.tcx.expr_ty(cast_exp).sty {
|
||||
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)),
|
||||
|
|
|
@ -47,7 +47,7 @@ impl LintPass for UnusedLabel {
|
|||
}
|
||||
|
||||
impl LateLintPass for UnusedLabel {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, fn_id: ast::NodeId) {
|
||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Expr, span: Span, fn_id: ast::NodeId) {
|
||||
if in_macro(cx, span) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -368,11 +368,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_expr(e);
|
||||
// TODO: _ty
|
||||
}
|
||||
ExprClosure(cap, _, ref b, _) => {
|
||||
ExprClosure(cap, _, ref e, _) => {
|
||||
let c: fn(_, _, _, _) -> _ = ExprClosure;
|
||||
c.hash(&mut self.s);
|
||||
cap.hash(&mut self.s);
|
||||
self.hash_block(b);
|
||||
self.hash_expr(e);
|
||||
}
|
||||
ExprField(ref e, ref f) => {
|
||||
let c: fn(_, _) -> _ = ExprField;
|
||||
|
|
|
@ -135,7 +135,7 @@ fn has_attr(attrs: &[Attribute]) -> bool {
|
|||
fn print_decl(cx: &LateContext, decl: &hir::Decl) {
|
||||
match decl.node {
|
||||
hir::DeclLocal(ref local) => {
|
||||
println!("local variable of type {}", cx.tcx.node_id_to_type(local.id));
|
||||
println!("local variable of type {}", cx.tcx.tables().node_id_to_type(local.id));
|
||||
println!("pattern:");
|
||||
print_pat(cx, &local.pat, 0);
|
||||
if let Some(ref e) = local.init {
|
||||
|
@ -149,7 +149,7 @@ fn print_decl(cx: &LateContext, decl: &hir::Decl) {
|
|||
|
||||
fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
|
||||
let ind = " ".repeat(indent);
|
||||
let ty = cx.tcx.node_id_to_type(expr.id);
|
||||
let ty = cx.tcx.tables().node_id_to_type(expr.id);
|
||||
println!("{}+", ind);
|
||||
match expr.node {
|
||||
hir::ExprBox(ref e) => {
|
||||
|
@ -350,25 +350,25 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
|
|||
}
|
||||
}
|
||||
hir::ItemUse(ref path) => println!("{:?}", path.node),
|
||||
hir::ItemStatic(..) => println!("static item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
|
||||
hir::ItemConst(..) => println!("const item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
|
||||
hir::ItemStatic(..) => (), //println!("static item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
|
||||
hir::ItemConst(..) => (), //println!("const item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
|
||||
hir::ItemFn(..) => {
|
||||
let item_ty = cx.tcx.opt_lookup_item_type(did);
|
||||
println!("function: {:#?}", item_ty);
|
||||
//let item_ty = cx.tcx.opt_lookup_item_type(did);
|
||||
//println!("function: {:#?}", item_ty);
|
||||
},
|
||||
hir::ItemMod(..) => println!("module"),
|
||||
hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
|
||||
hir::ItemTy(..) => {
|
||||
println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
//println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
},
|
||||
hir::ItemEnum(..) => {
|
||||
println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
//println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
},
|
||||
hir::ItemStruct(..) => {
|
||||
println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
//println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
},
|
||||
hir::ItemUnion(..) => {
|
||||
println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
//println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did));
|
||||
},
|
||||
hir::ItemTrait(..) => {
|
||||
println!("trait decl");
|
||||
|
|
|
@ -429,7 +429,12 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
|
|||
if let Some(node) = enclosing_node {
|
||||
match node {
|
||||
Node::NodeBlock(block) => Some(block),
|
||||
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref block), .. }) => Some(block),
|
||||
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref expr), .. }) => {
|
||||
match expr.node {
|
||||
ExprBlock(ref block) => Some(block),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
|
@ -696,8 +701,9 @@ 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> {
|
||||
let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item);
|
||||
let fn_sig = cx.tcx.node_id_to_type(fn_item).fn_sig().subst(cx.tcx, parameter_env.free_substs);
|
||||
let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig);
|
||||
let fn_def_id = cx.tcx.map.local_def_id(fn_item);
|
||||
let fn_sig = cx.tcx.item_type(fn_def_id).fn_sig();
|
||||
let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, fn_sig);
|
||||
fn_sig.output
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ impl LateLintPass for Pass {
|
|||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
|
||||
if_let_chain!{[
|
||||
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.expr_ty_adjusted(expr).sty,
|
||||
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.tables().expr_ty_adjusted(expr).sty,
|
||||
let ty::TypeVariants::TySlice(..) = ty.ty.sty,
|
||||
let ExprAddrOf(_, ref addressee) = expr.node,
|
||||
let Some(vec_args) = higher::vec_macro(cx, addressee),
|
||||
|
@ -48,7 +48,7 @@ impl LateLintPass 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.tcx.expr_ty_adjusted(arg)), cx.tcx.map.get_parent(expr.id)),
|
||||
is_copy(cx, vec_type(cx.tcx.tables().expr_ty_adjusted(arg)), cx.tcx.map.get_parent(expr.id)),
|
||||
], {
|
||||
// report the error around the `vec!` not inside `<std macros>:`
|
||||
let span = cx.sess().codemap().source_callsite(arg.span);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(plugin, inclusive_range_syntax)]
|
||||
#![feature(dotdot_in_tuple_patterns)]
|
||||
#![plugin(clippy)]
|
||||
|
||||
#![allow(dead_code, no_effect, unnecessary_operation)]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(plugin, never_type)]
|
||||
#![plugin(clippy)]
|
||||
#![deny(diverging_sub_expression)]
|
||||
#![allow(match_same_arms, logic_bug)]
|
||||
|
||||
#[allow(empty_loop)]
|
||||
fn diverge() -> ! { loop {} }
|
||||
|
@ -16,8 +17,6 @@ fn main() {
|
|||
let b = true;
|
||||
b || diverge(); //~ ERROR sub-expression diverges
|
||||
b || A.foo(); //~ ERROR sub-expression diverges
|
||||
let y = (5, diverge(), 6); //~ ERROR sub-expression diverges
|
||||
println!("{}", y.1);
|
||||
}
|
||||
|
||||
#[allow(dead_code, unused_variables)]
|
||||
|
@ -26,16 +25,16 @@ fn foobar() {
|
|||
let x = match 5 {
|
||||
4 => return,
|
||||
5 => continue,
|
||||
6 => (println!("foo"), return), //~ ERROR sub-expression diverges
|
||||
7 => (println!("bar"), continue), //~ ERROR sub-expression diverges
|
||||
6 => true || return, //~ ERROR sub-expression diverges
|
||||
7 => true || continue, //~ ERROR sub-expression diverges
|
||||
8 => break,
|
||||
9 => diverge(),
|
||||
3 => (println!("moo"), diverge()), //~ ERROR sub-expression diverges
|
||||
3 => true || diverge(), //~ ERROR sub-expression diverges
|
||||
10 => match 42 {
|
||||
99 => return,
|
||||
_ => ((), panic!("boo")),
|
||||
_ => true || panic!("boo"),
|
||||
},
|
||||
_ => (println!("boo"), break), //~ ERROR sub-expression diverges
|
||||
_ => true || break, //~ ERROR sub-expression diverges
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ fn main() {
|
|||
true || true; //~ERROR equal expressions
|
||||
//~|ERROR this boolean expression can be simplified
|
||||
|
||||
let a: u32 = unimplemented!();
|
||||
let b: u32 = unimplemented!();
|
||||
let a: u32 = 0;
|
||||
let b: u32 = 0;
|
||||
|
||||
a == b && b == a; //~ERROR equal expressions
|
||||
//~|ERROR this boolean expression can be simplified
|
||||
|
|
Loading…
Add table
Reference in a new issue