1
Fork 0

Rustup to rustc 1.15.0-nightly (0ed951993 2016-11-14)

This commit is contained in:
mcarton 2016-11-16 21:57:56 +01:00
parent bad26a5aca
commit 19c5f5394b
No known key found for this signature in database
GPG key ID: 5E427C794CBA45E8
53 changed files with 237 additions and 246 deletions

View file

@ -59,7 +59,7 @@ impl LateLintPass for Arithmetic {
hir::BiShr | hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => return, 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() { if l_ty.is_integral() && r_ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span); self.span = Some(expr.span);
@ -69,7 +69,7 @@ impl LateLintPass for Arithmetic {
} }
} }
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { 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() { if ty.is_integral() {
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
self.span = Some(expr.span); self.span = Some(expr.span);

View file

@ -59,7 +59,7 @@ impl LateLintPass for ArrayIndexing {
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
if let hir::ExprIndex(ref array, ref index) = e.node { if let hir::ExprIndex(ref array, ref index) = e.node {
// Array with known size can be checked statically // 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 { if let ty::TyArray(_, size) = ty.sty {
let size = ConstInt::Infer(size as u64); let size = ConstInt::Infer(size as u64);

View file

@ -81,11 +81,11 @@ impl LateLintPass for AssignOps {
if let hir::ExprBinary(binop, ref l, ref r) = rhs.node { if let hir::ExprBinary(binop, ref l, ref r) = rhs.node {
if op.node == binop.node { if op.node == binop.node {
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { 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() { if ty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics 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() { if rty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics return; // implements_trait does not work with generics
} }
@ -116,11 +116,11 @@ impl LateLintPass for AssignOps {
hir::ExprAssign(ref assignee, ref e) => { hir::ExprAssign(ref assignee, ref e) => {
if let hir::ExprBinary(op, ref l, ref r) = e.node { if let hir::ExprBinary(op, ref l, ref r) = e.node {
let lint = |assignee: &hir::Expr, rhs: &hir::Expr| { 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() { if ty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics 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() { if rty.walk_shallow().next().is_some() {
return; // implements_trait does not work with generics return; // implements_trait does not work with generics
} }

View file

@ -152,8 +152,8 @@ impl LateLintPass for AttrPass {
} }
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool { fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, ref block) = item.node { if let ItemFn(_, _, _, _, _, ref expr) = item.node {
is_relevant_block(cx, block) is_relevant_expr(cx, expr)
} else { } else {
false false
} }
@ -161,7 +161,7 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool { fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
match item.node { match item.node {
ImplItemKind::Method(_, ref block) => is_relevant_block(cx, block), ImplItemKind::Method(_, ref expr) => is_relevant_expr(cx, expr),
_ => false, _ => false,
} }
} }
@ -169,7 +169,7 @@ fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool { fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
match item.node { match item.node {
MethodTraitItem(_, None) => true, MethodTraitItem(_, None) => true,
MethodTraitItem(_, Some(ref block)) => is_relevant_block(cx, block), MethodTraitItem(_, Some(ref expr)) => is_relevant_expr(cx, expr),
_ => false, _ => false,
} }
} }

View file

@ -55,17 +55,9 @@ struct ExVisitor<'v> {
impl<'v> Visitor<'v> for ExVisitor<'v> { impl<'v> Visitor<'v> for ExVisitor<'v> {
fn visit_expr(&mut self, expr: &'v Expr) { fn visit_expr(&mut self, expr: &'v Expr) {
if let ExprClosure(_, _, ref block, _) = expr.node { if let ExprClosure(_, _, ref expr, _) = expr.node {
let complex = { let complex = {
if block.stmts.is_empty() { matches!(expr.node, ExprBlock(_))
if let Some(ref ex) = block.expr {
matches!(ex.node, ExprBlock(_))
} else {
false
}
} else {
true
}
}; };
if complex { if complex {
self.found_block = Some(expr); self.found_block = Some(expr);

View file

@ -392,7 +392,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
match e.node { match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e), ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => { 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); self.bool_expr(e);
} else { } else {
walk_expr(self, e); walk_expr(self, e);

View file

@ -120,8 +120,8 @@ impl LateLintPass for CopyAndPaste {
} }
let (conds, blocks) = if_sequence(expr); let (conds, blocks) = if_sequence(expr);
lint_same_then_else(cx, blocks.as_slice()); lint_same_then_else(cx, &blocks);
lint_same_cond(cx, conds.as_slice()); lint_same_cond(cx, &conds);
lint_match_arms(cx, expr); 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 /// Eg. would return `([a, b], [c, d, e])` for the expression
/// `if a { c } else if b { d } else { e }`. /// `if a { c } else if b { d } else { e }`.
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) { fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
let mut conds = SmallVector::zero(); let mut conds = SmallVector::new();
let mut blocks = SmallVector::zero(); let mut blocks = SmallVector::new();
while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node { while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
conds.push(&**cond); 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) => { PatKind::Binding(_, ref ident, ref as_pat) => {
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) { 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 { if let Some(ref as_pat) = *as_pat {
bindings_impl(cx, as_pat, map); bindings_impl(cx, as_pat, map);

View file

@ -42,12 +42,12 @@ impl LintPass for CyclomaticComplexity {
} }
impl 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) { if in_macro(cx, span) {
return; return;
} }
let cfg = CFG::new(cx.tcx, block); let cfg = CFG::new(cx.tcx, expr);
let n = cfg.graph.len_nodes() as u64; let n = cfg.graph.len_nodes() as u64;
let e = cfg.graph.len_edges() as u64; let e = cfg.graph.len_edges() as u64;
if e + 2 < n { if e + 2 < n {
@ -62,9 +62,9 @@ impl CyclomaticComplexity {
returns: 0, returns: 0,
tcx: &cx.tcx, tcx: &cx.tcx,
}; };
helper.visit_block(block); helper.visit_expr(expr);
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper; 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) { let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
returns returns
} else { } else {
@ -92,22 +92,22 @@ impl CyclomaticComplexity {
impl LateLintPass for CyclomaticComplexity { impl LateLintPass for CyclomaticComplexity {
fn check_item(&mut self, cx: &LateContext, item: &Item) { 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") { 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) { fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if let ImplItemKind::Method(_, ref block) = item.node { if let ImplItemKind::Method(_, ref expr) = item.node {
self.check(cx, block, item.span); self.check(cx, expr, item.span);
} }
} }
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) { fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if let MethodTraitItem(_, Some(ref block)) = item.node { if let MethodTraitItem(_, Some(ref expr)) = item.node {
self.check(cx, block, item.span); 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, _) => { ExprCall(ref callee, _) => {
walk_expr(self, e); 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 { match ty.sty {
ty::TyFnDef(_, _, ty) | ty::TyFnDef(_, _, ty) |
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => { ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {

View file

@ -73,7 +73,7 @@ impl LintPass for Derive {
impl LateLintPass for Derive { impl LateLintPass for Derive {
fn check_item(&mut self, cx: &LateContext, item: &Item) { fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node { 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); let is_automatically_derived = is_automatically_derived(&*item.attrs);
check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived); check_hash_peq(cx, item.span, trait_ref, ty, is_automatically_derived);

View file

@ -52,7 +52,7 @@ impl LateLintPass for Pass {
} }
fn check_drop_arg(cx: &LateContext, call_span: Span, arg: &Expr) { 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 { if let ty::TyRef(..) = arg_ty.sty {
span_note_and_lint(cx, span_note_and_lint(cx,
DROP_REF, DROP_REF,

View file

@ -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 ExprAddrOf(_, ref key) = params[1].node
], { ], {
let map = &params[0]; let map = &params[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) { return if match_type(cx, obj_ty, &paths::BTREEMAP) {
Some(("BTreeMap", map, key)) Some(("BTreeMap", map, key))

View file

@ -5,7 +5,6 @@ use rustc::infer::InferCtxt;
use rustc::lint::*; use rustc::lint::*;
use rustc::middle::expr_use_visitor::*; use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::{cmt, Categorization}; use rustc::middle::mem_categorization::{cmt, Categorization};
use rustc::ty::adjustment::AutoAdjustment;
use rustc::ty; use rustc::ty;
use rustc::ty::layout::TargetDataLayout; use rustc::ty::layout::TargetDataLayout;
use rustc::util::nodemap::NodeSet; use rustc::util::nodemap::NodeSet;
@ -62,7 +61,7 @@ impl LintPass for Pass {
} }
impl LateLintPass 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 param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env); 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, fn borrow(&mut self, borrow_id: NodeId, _: Span, cmt: cmt<'tcx>, _: &ty::Region, _: ty::BorrowKind,
loan_cause: LoanCause) { loan_cause: LoanCause) {
use rustc::ty::adjustment::Adjust;
if let Categorization::Local(lid) = cmt.cat { if let Categorization::Local(lid) = cmt.cat {
if self.set.contains(&lid) { if self.set.contains(&lid) {
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
.tables .tables
.borrow() .borrow()
.adjustments .adjustments
.get(&borrow_id) { .get(&borrow_id)
.map(|a| &a.kind) {
if LoanCause::AutoRef == loan_cause { if LoanCause::AutoRef == loan_cause {
// x.foo() // x.foo()
if adj.autoderefs == 0 { if autoderefs == 0 {
self.set.remove(&lid); // Used without autodereffing (i.e. x.clone()) self.set.remove(&lid); // Used without autodereffing (i.e. x.clone())
} }
} else { } 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 { } else if LoanCause::AddrOf == loan_cause {
// &x // &x
if let Some(&AutoAdjustment::AdjustDerefRef(adj)) = self.tcx if let Some(&Adjust::DerefRef { autoderefs, .. }) = self.tcx
.tables .tables
.borrow() .borrow()
.adjustments .adjustments
.get(&self.tcx .get(&self.tcx
.map .map
.get_parent_node(borrow_id)) { .get_parent_node(borrow_id))
if adj.autoderefs <= 1 { .map(|a| &a.kind) {
if autoderefs <= 1 {
// foo(&x) where no extra autoreffing is happening // foo(&x) where no extra autoreffing is happening
self.set.remove(&lid); self.set.remove(&lid);
} }

View file

@ -48,60 +48,53 @@ impl LateLintPass for EtaPass {
} }
fn check_closure(cx: &LateContext, expr: &Expr) { fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, ref blk, _) = expr.node { if let ExprClosure(_, ref decl, ref ex, _) = expr.node {
if !blk.stmts.is_empty() { if let ExprCall(ref caller, ref args) = ex.node {
// || {foo(); bar()}; can't be reduced here if args.len() != decl.inputs.len() {
return; // Not the same number of arguments, there
} // is no way the closure is the same as the function
return;
if let Some(ref ex) = blk.expr { }
if let ExprCall(ref caller, ref args) = ex.node { if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
if args.len() != decl.inputs.len() { // Are the expression or the arguments type-adjusted? Then we need the closure
// Not the same number of arguments, there return;
// is no way the closure is the same as the function }
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; for (a1, a2) in decl.inputs.iter().zip(args) {
} if let PatKind::Binding(_, ident, _) = a1.pat.node {
let fn_ty = cx.tcx.expr_ty(caller); // XXXManishearth Should I be checking the binding mode here?
match fn_ty.sty { if let ExprPath(None, ref p) = a2.node {
// Is it an unsafe function? They don't implement the closure traits if p.segments.len() != 1 {
ty::TyFnDef(_, _, fn_ty) | // If it's a proper path, it can't be a local variable
ty::TyFnPtr(fn_ty) => {
if fn_ty.unsafety == Unsafety::Unsafe ||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
return; return;
} }
} if p.segments[0].name != ident.node {
_ => (), // The two idents should be the same
}
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 {
return; return;
} }
} else { } else {
return; 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);
}
});
} }
} }
} }

View file

@ -126,7 +126,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
ExprAgain(_) | ExprAgain(_) |
ExprBreak(_) | ExprBreak(_) |
ExprRet(_) => self.report_diverging_sub_expr(e), 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::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty { 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); self.report_diverging_sub_expr(e);

View file

@ -132,7 +132,7 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
let Some(fun) = resolve_node(cx, args[1].id), let Some(fun) = resolve_node(cx, args[1].id),
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD), 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); return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
}} }}

View file

@ -69,7 +69,7 @@ impl LintPass for Functions {
} }
impl LateLintPass 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::*; use rustc::hir::map::Node::*;
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) { 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) { 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 // don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust { if sig.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span); self.check_arg_number(cx, &sig.decl, item.span);
} }
if let Some(ref block) = *block { if let Some(ref expr) = *expr {
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.id); 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) { 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<_>>(); 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, 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) { fn visit_expr(&mut self, expr: &'v hir::Expr) {
match expr.node { match expr.node {
hir::ExprCall(ref f, ref args) => { 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) { if type_is_unsafe_function(ty) {
for arg in args { for arg in args {

View file

@ -1,6 +1,6 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ty::{self, ImplOrTraitItem}; use rustc::ty;
use rustc::hir::*; use rustc::hir::*;
use syntax::ast::{Lit, LitKind, Name}; use syntax::ast::{Lit, LitKind, Name};
use syntax::codemap::{Span, Spanned}; 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 let Some(i) = impl_items.iter().find(|i| is_named_self(i, "len")) {
if cx.access_levels.is_exported(i.id) { 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, span_lint(cx,
LEN_WITHOUT_IS_EMPTY, 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. /// Check if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
/// Get an `ImplOrTraitItem` and return true if it matches `is_empty(self)`. /// Get an `AssociatedItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(item: &ImplOrTraitItem) -> bool { fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool {
if let ty::MethodTraitItem(ref method) = *item { if let ty::AssociatedKind::Method = item.kind {
method.name.as_str() == "is_empty" && method.fty.sig.skip_binder().inputs.len() == 1 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 { } else {
false 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. /// Check the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { 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.inherent_impls.borrow().get(&id).map_or(false, |impls| impls.iter().any(|imp| {
cx.tcx.impl_or_trait_items(*imp).iter().any(|item| { cx.tcx.associated_items(*imp).any(|item| {
is_is_empty(&cx.tcx.impl_or_trait_item(*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 { match ty.sty {
ty::TyTrait(_) => { ty::TyTrait(_) => {
cx.tcx cx.tcx
.impl_or_trait_items(ty.ty_to_def_id().expect("trait impl not found")) .associated_items(ty.ty_to_def_id().expect("trait impl not found"))
.iter() .any(|item| is_is_empty(cx, &item))
.any(|item| is_is_empty(&cx.tcx.impl_or_trait_item(*item)))
} }
ty::TyProjection(_) => ty.ty_to_def_id().map_or(false, |id| has_is_empty_impl(cx, id)), 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), ty::TyAdt(id, _) => has_is_empty_impl(cx, id.did),

View file

@ -3,7 +3,6 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(collections)] #![feature(collections)]
#![feature(custom_attribute)] #![feature(custom_attribute)]
#![feature(dotdot_in_tuple_patterns)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]

View file

@ -247,8 +247,8 @@ impl<'v, 't> RefVisitor<'v, 't> {
match def { match def {
Def::TyAlias(def_id) | Def::TyAlias(def_id) |
Def::Struct(def_id) => { Def::Struct(def_id) => {
let type_scheme = self.cx.tcx.lookup_item_type(def_id); let generics = self.cx.tcx.item_generics(def_id);
for _ in type_scheme.generics.regions.as_slice() { for _ in generics.regions.as_slice() {
self.record(&None); self.record(&None);
} }
} }

View file

@ -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` /// Check for `for` loops over `Option`s and `Results`
fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) { 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) { if match_type(cx, ty, &paths::OPTION) {
span_help_and_lint(cx, span_help_and_lint(cx,
FOR_LOOP_OVER_OPTION, 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), _ => (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) { if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) {
span_lint_and_then(cx, span_lint_and_then(cx,
FOR_KV_MAP, 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 { fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
// no walk_ptrs_ty: calling iter() on a reference can make sense because it // no walk_ptrs_ty: calling iter() on a reference can make sense because it
// will allow further borrows afterwards // will allow further borrows afterwards
let ty = cx.tcx.expr_ty(e); let ty = cx.tcx.tables().expr_ty(e);
is_iterable_array(ty) || is_iterable_array(ty) ||
match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC) ||
match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::LINKED_LIST) ||

View file

@ -30,11 +30,8 @@ impl LateLintPass for Pass {
if let ExprMethodCall(name, _, ref args) = expr.node { if let ExprMethodCall(name, _, ref args) = expr.node {
if name.node.as_str() == "map" && args.len() == 2 { if name.node.as_str() == "map" && args.len() == 2 {
match args[1].node { match args[1].node {
ExprClosure(_, ref decl, ref blk, _) => { ExprClosure(_, ref decl, ref closure_expr, _) => {
if_let_chain! {[ 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 // nothing special in the argument, besides reference bindings
// (e.g. .map(|&x| x) ) // (e.g. .map(|&x| x) )
let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat), let Some(arg_ident) = get_arg_name(&*decl.inputs[0].pat),
@ -44,7 +41,7 @@ impl LateLintPass for Pass {
// look for derefs, for .map(|x| *x) // look for derefs, for .map(|x| *x)
if only_derefs(cx, &*closure_expr, arg_ident) && if only_derefs(cx, &*closure_expr, arg_ident) &&
// .cloned() only removes one level of indirection, don't lint on more // .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!( span_help_and_lint(cx, MAP_CLONE, expr.span, &format!(
"you seem to be using .map() to clone the contents of an {}, consider \ "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> { fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static str> {
if match_trait_method(cx, expr, &paths::ITERATOR) { if match_trait_method(cx, expr, &paths::ITERATOR) {
Some("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") Some("Option")
} else { } else {
None None

View file

@ -159,7 +159,7 @@ fn check_single_match(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
// allow match arms with just expressions // allow match arms with just expressions
return; 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 { if ty.sty != ty::TyBool || cx.current_level(MATCH_BOOL) == Allow {
check_single_match_single_pattern(cx, ex, arms, expr, els); check_single_match_single_pattern(cx, ex, arms, expr, els);
check_single_match_opt_like(cx, ex, arms, expr, ty, 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) { fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
// type of expression == bool // 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, span_lint_and_then(cx,
MATCH_BOOL, MATCH_BOOL,
expr.span, 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]) { 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 ranges = all_ranges(cx, arms);
let type_ranges = type_ranges(&ranges); let type_ranges = type_ranges(&ranges);
if !type_ranges.is_empty() { if !type_ranges.is_empty() {

View file

@ -33,7 +33,7 @@ impl LateLintPass for MemForget {
if let ExprPath(None, _) = path_expr.node { if let ExprPath(None, _) = path_expr.node {
let def_id = cx.tcx.expect_def(path_expr.id).def_id(); let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::MEM_FORGET) { 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() { if match forgot_ty.ty_adt_def() {
Some(def) => def.has_dtor(), Some(def) => def.has_dtor(),

View file

@ -573,7 +573,7 @@ impl LateLintPass for Pass {
lint_or_fun_call(cx, expr, &name.node.as_str(), args); 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" { if args.len() == 1 && name.node.as_str() == "clone" {
lint_clone_on_copy(cx, expr, &args[0], self_ty); 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 // 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); let is_copy = is_copy(cx, ty, item.id);
for &(ref conv, self_kinds) in &CONVENTIONS { for &(ref conv, self_kinds) in &CONVENTIONS {
if_let_chain! {[ if_let_chain! {[
@ -680,7 +680,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
.as_str(); .as_str();
if ["default", "new"].contains(&path) { 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) { let default_trait_id = if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT) {
default_trait_id default_trait_id
} else { } else {
@ -724,7 +724,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[P<hi
"else"), "else"),
(&paths::RESULT, true, &["or", "unwrap_or"], "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)) = 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)) { 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. /// 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::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 parent = cx.tcx.map.get_parent(expr.id);
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent); let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, parent);
if let ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) = arg_ty.sty { 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, expr.span,
"using `clone` on a `Copy` type", "using `clone` on a `Copy` type",
|db| if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { |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())); db.span_suggestion(expr.span, "try dereferencing it", format!("{}", snip.deref()));
} else { } else {
db.span_suggestion(expr.span, "try removing the `clone` call", format!("{}", snip)); 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) { 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) { if !match_type(cx, obj_ty, &paths::VEC) {
return; 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) { 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| { 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, 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 // Type of MethodArgs is potentially a Vec
fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){ fn lint_iter_nth(cx: &LateContext, expr: &hir::Expr, iter_args: &MethodArgs, is_mut: bool){
let mut_str = if is_mut { "_mut" } else {""}; 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" "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" "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" "VecDeque"
} }
else { 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) { 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, // Note: we don't want to lint `get_mut().unwrap` for HashMap or BTreeMap,
// because they do not implement `IndexMut` // 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() { let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() {
"slice" "slice"
} else if match_type(cx, expr_ty, &paths::VEC) { } 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 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::Sugg::hir_opt(cx, &*args[0]).map(|sugg| {
sugg.addr() 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 // Type of MethodArgs is potentially a Vec
/// lint use of `unwrap()` for `Option`s and `Result`s /// lint use of `unwrap()` for `Option`s and `Result`s
fn lint_unwrap(cx: &LateContext, expr: &hir::Expr, unwrap_args: &MethodArgs) { 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) { let mess = if match_type(cx, obj_ty, &paths::OPTION) {
Some((OPTION_UNWRAP_USED, "an Option", "None")) 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 /// lint use of `ok().expect()` for `Result`s
fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) { fn lint_ok_expect(cx: &LateContext, expr: &hir::Expr, ok_args: &MethodArgs) {
// lint if the caller of `ok()` is a `Result` // lint if the caller of `ok()` is a `Result`
if match_type(cx, cx.tcx.expr_ty(&ok_args[0]), &paths::RESULT) { if match_type(cx, cx.tcx.tables().expr_ty(&ok_args[0]), &paths::RESULT) {
let result_type = cx.tcx.expr_ty(&ok_args[0]); let result_type = cx.tcx.tables().expr_ty(&ok_args[0]);
if let Some(error_type) = get_error_type(cx, result_type) { if let Some(error_type) = get_error_type(cx, result_type) {
if has_debug_impl(error_type, cx) { if has_debug_impl(error_type, cx) {
span_lint(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 /// 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) { 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` // 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 // lint message
let msg = "called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling \ 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"; `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 /// 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) { 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` // 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 // lint message
let msg = "called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling \ 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"; `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, let hir::ExprPath(None, ref path) = fun.node,
path.segments.len() == 1 && path.segments[0].name.as_str() == "Some" 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 { if self_ty.sty != ty::TyStr {
return false; return false;

View file

@ -168,7 +168,7 @@ impl LintPass for Pass {
} }
impl LateLintPass 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 { if let FnKind::Closure(_) = k {
// Does not apply to closures // Does not apply to closures
return; return;
@ -353,14 +353,14 @@ fn is_allowed(cx: &LateContext, expr: &Expr) -> bool {
} }
fn is_float(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) { fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: Span) {
let (arg_ty, snip) = match expr.node { let (arg_ty, snip) = match expr.node {
ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) if args.len() == 1 => { 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) { 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 { } else {
return; 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 => { ExprCall(ref path, ref v) if v.len() == 1 => {
if let ExprPath(None, ref path) = path.node { if let ExprPath(None, ref path) = path.node {
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) { 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 { } else {
return; return;
} }
@ -379,7 +379,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
_ => return, _ => 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() { let partial_eq_trait_id = match cx.tcx.lang_items.eq_trait() {
Some(id) => id, Some(id) => id,
None => return, 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 { fn is_str_arg(cx: &LateContext, args: &[P<Expr>]) -> bool {
args.len() == 1 && 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 /// Heuristic to see if an expression is used. Should be compatible with `unused_variables`'s idea

View file

@ -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(); let mut registered_names: HashMap<String, Span> = HashMap::new();
for arg in &decl.inputs { for arg in &decl.inputs {

View file

@ -147,10 +147,7 @@ impl LateLintPass for MissingDoc {
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) { fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
// If the method is an impl for a trait, don't doc. // If the method is an impl for a trait, don't doc.
let def_id = cx.tcx.map.local_def_id(impl_item.id); let def_id = cx.tcx.map.local_def_id(impl_item.id);
match cx.tcx.impl_or_trait_items.borrow() match cx.tcx.associated_item(def_id).container {
.get(&def_id)
.expect("missing method descriptor?!")
.container() {
ty::TraitContainer(_) => return, ty::TraitContainer(_) => return,
ty::ImplContainer(cid) => { ty::ImplContainer(cid) => {
if cx.tcx.impl_trait_ref(cid).is_some() { if cx.tcx.impl_trait_ref(cid).is_some() {

View file

@ -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 { } else if let hir::ExprAddrOf(hir::MutMutable, ref e) = expr.node {
if let hir::ExprAddrOf(hir::MutMutable, _) = e.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"); 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, span_lint(self.cx,
MUT_MUT, MUT_MUT,
expr.span, expr.span,

View file

@ -56,7 +56,7 @@ pub struct MutexAtomic;
impl LateLintPass for MutexAtomic { impl LateLintPass for MutexAtomic {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { 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 let ty::TyAdt(_, subst) = ty.sty {
if match_type(cx, ty, &paths::MUTEX) { if match_type(cx, ty, &paths::MUTEX) {
let mutex_param = &subst.type_at(0).sty; let mutex_param = &subst.type_at(0).sty;

View file

@ -4,9 +4,8 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode}; use rustc::hir::{ExprAddrOf, Expr, MutImmutable, Pat, PatKind, BindingMode};
use rustc::ty::TyRef; use rustc::ty;
use utils::{span_lint, in_macro}; use utils::{span_lint, in_macro};
use rustc::ty::adjustment::AutoAdjustment::AdjustDerefRef;
/// **What it does:** Checks for address of operations (`&`) that are going to /// **What it does:** Checks for address of operations (`&`) that are going to
/// be dereferenced immediately by the compiler. /// be dereferenced immediately by the compiler.
@ -41,9 +40,9 @@ impl LateLintPass for NeedlessBorrow {
return; return;
} }
if let ExprAddrOf(MutImmutable, ref inner) = e.node { if let ExprAddrOf(MutImmutable, ref inner) = e.node {
if let TyRef(..) = cx.tcx.expr_ty(inner).sty { if let ty::TyRef(..) = cx.tcx.tables().expr_ty(inner).sty {
if let Some(&AdjustDerefRef(ref deref)) = cx.tcx.tables.borrow().adjustments.get(&e.id) { if let Some(&ty::adjustment::Adjust::DerefRef { autoderefs, autoref, .. }) = cx.tcx.tables.borrow().adjustments.get(&e.id).map(|a| &a.kind) {
if deref.autoderefs > 1 && deref.autoref.is_some() { if autoderefs > 1 && autoref.is_some() {
span_lint(cx, span_lint(cx,
NEEDLESS_BORROW, NEEDLESS_BORROW,
e.span, e.span,
@ -59,9 +58,9 @@ impl LateLintPass for NeedlessBorrow {
return; return;
} }
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node { 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 tam.mutbl == MutImmutable {
if let TyRef(..) = tam.ty.sty { if let ty::TyRef(..) = tam.ty.sty {
span_lint(cx, span_lint(cx,
NEEDLESS_BORROW, NEEDLESS_BORROW,
pat.span, pat.span,

View file

@ -33,7 +33,7 @@ impl LintPass for Pass {
impl LateLintPass for Pass { impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node { 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 let TyAdt(def, _) = ty.sty {
if fields.len() == def.struct_variant().fields.len() { if fields.len() == def.struct_variant().fields.len() {
span_lint(cx, span_lint(cx,

View file

@ -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 Constant::Int(ref ci) = consts::lit_to_constant(&l.node),
let Some(val) = ci.to_u64(), let Some(val) = ci.to_u64(),
val == 1, val == 1,
cx.tcx.expr_ty(exp).is_integral() cx.tcx.tables().expr_ty(exp).is_integral()
], { ], {
span_lint(cx, span_lint(cx,
NEG_MULTIPLY, NEG_MULTIPLY,

View file

@ -90,7 +90,7 @@ impl LintPass for NewWithoutDefault {
} }
impl LateLintPass 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) { if in_external_macro(cx, span) {
return; return;
} }
@ -102,8 +102,7 @@ impl LateLintPass for NewWithoutDefault {
} }
if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) { if decl.inputs.is_empty() && name.as_str() == "new" && cx.access_levels.is_reachable(id) {
let self_ty = cx.tcx let self_ty = cx.tcx
.lookup_item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id))) .item_type(cx.tcx.map.local_def_id(cx.tcx.map.get_parent(id)));
.ty;
if_let_chain!{[ if_let_chain!{[
self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics self_ty.walk_shallow().next().is_none(), // implements_trait does not work with generics
same_tys(cx, self_ty, return_ty(cx, id), id), same_tys(cx, self_ty, return_ty(cx, id), id),

View file

@ -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; 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, ""); let some_expr_string = snippet(cx, y[0].span, "");
if print::path_to_string(x) == "Some" && is_result_type { if print::path_to_string(x) == "Some" && is_result_type {
span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span, span_help_and_lint(cx, IF_LET_SOME_RESULT, expr.span,

View file

@ -35,7 +35,7 @@ impl LintPass for NonSensical {
impl LateLintPass for NonSensical { impl LateLintPass for NonSensical {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) { fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprMethodCall(ref name, _, ref arguments) = e.node { 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) { if name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
let mut options = Vec::new(); let mut options = Vec::new();
get_open_options(cx, &arguments[0], &mut options); 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)>) { fn get_open_options(cx: &LateContext, argument: &Expr, options: &mut Vec<(OpenOption, Argument)>) {
if let ExprMethodCall(ref name, _, ref arguments) = argument.node { 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 // 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 { if match_type(cx, obj_ty, &paths::OPEN_OPTIONS) && arguments.len() >= 2 {

View file

@ -39,8 +39,8 @@ impl LateLintPass for OverflowCheckConditional {
let Expr_::ExprPath(_, ref path2) = ident2.node, let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = second.node, let Expr_::ExprPath(_, ref path3) = second.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(), cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral() cx.tcx.tables().expr_ty(ident2).is_integral()
], { ], {
if let BinOp_::BiLt = op.node { if let BinOp_::BiLt = op.node {
if let BinOp_::BiAdd = op2.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 path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = first.node, let Expr_::ExprPath(_, ref path3) = first.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0], &path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.expr_ty(ident1).is_integral(), cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.expr_ty(ident2).is_integral() cx.tcx.tables().expr_ty(ident2).is_integral()
], { ], {
if let BinOp_::BiGt = op.node { if let BinOp_::BiGt = op.node {
if let BinOp_::BiAdd = op2.node { if let BinOp_::BiAdd = op2.node {

View file

@ -91,7 +91,8 @@ impl LateLintPass for PointerPass {
} }
fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { 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) { for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) {
if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty {

View file

@ -89,7 +89,7 @@ impl LateLintPass for StepByZero {
fn has_step_by(cx: &LateContext, expr: &Expr) -> bool { fn has_step_by(cx: &LateContext, expr: &Expr) -> bool {
// No need for walk_ptrs_ty here because step_by moves self, so it // No need for walk_ptrs_ty here because step_by moves self, so it
// can't be called on a borrowed range. // 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 // Note: `RangeTo`, `RangeToInclusive` and `RangeFull` don't have step_by
match_type(cx, ty, &paths::RANGE) match_type(cx, ty, &paths::RANGE)

View file

@ -91,7 +91,7 @@ impl LateLintPass for Pass {
if_let_chain!{[ if_let_chain!{[
self.last.is_none(), self.last.is_none(),
let Some(ref expr) = block.expr, 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"), let Some(span) = is_expn_of(cx, expr.span, "regex"),
], { ], {
if !self.spans.contains(&span) { if !self.spans.contains(&span) {

View file

@ -1,5 +1,5 @@
use rustc::lint::*; use rustc::lint::*;
use syntax::ast::*; use syntax::ast;
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind; use syntax::visit::FnKind;
@ -45,10 +45,10 @@ pub struct ReturnPass;
impl ReturnPass { impl ReturnPass {
// Check the final stmt or expr in a block for unnecessary return. // 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() { if let Some(stmt) = block.stmts.last() {
match stmt.node { 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)); 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. // 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 { match expr.node {
// simple return is always "bad" // 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); self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
} }
// a whole block? check it! // a whole block? check it!
ExprKind::Block(ref block) => { ast::ExprKind::Block(ref block) => {
self.check_block_return(cx, block); self.check_block_return(cx, block);
} }
// an if/if let expr, check both exprs // an if/if let expr, check both exprs
// note, if without else is going to be a type checking error anyways // note, if without else is going to be a type checking error anyways
// (except for unit type functions) so we don't match it // (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_block_return(cx, ifblock);
self.check_final_expr(cx, elsexpr, None); self.check_final_expr(cx, elsexpr, None);
} }
// a match expr, check all arms // a match expr, check all arms
ExprKind::Match(_, ref arms) => { ast::ExprKind::Match(_, ref arms) => {
for arm in arms { for arm in arms {
self.check_final_expr(cx, &arm.body, Some(arm.body.span)); self.check_final_expr(cx, &arm.body, Some(arm.body.span));
} }
@ -96,18 +96,18 @@ impl ReturnPass {
} }
// Check for "let x = EXPR; x" // 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(); let mut it = block.stmts.iter();
// we need both a let-binding stmt and an expr // we need both a let-binding stmt and an expr
if_let_chain! {[ if_let_chain! {[
let Some(ref retexpr) = it.next_back(), 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 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 Some(ref initexpr) = local.init,
let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
let ExprKind::Path(_, ref path) = retexpr.node, let ast::ExprKind::Path(_, ref path) = retexpr.node,
match_path_ast(path, &[&id.name.as_str()]), match_path_ast(path, &[&id.name.as_str()]),
!in_external_macro(cx, initexpr.span), !in_external_macro(cx, initexpr.span),
], { ], {
@ -129,11 +129,14 @@ impl LintPass for ReturnPass {
} }
impl EarlyLintPass for ReturnPass { impl EarlyLintPass for ReturnPass {
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) { fn check_fn(&mut self, cx: &EarlyContext, kind: FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) {
self.check_block_return(cx, block); 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); self.check_let_return(cx, block);
} }
} }

View file

@ -81,22 +81,22 @@ impl LintPass for Pass {
} }
impl LateLintPass for Pass { impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, block: &Block, _: Span, _: NodeId) { fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, expr: &Expr, _: Span, _: NodeId) {
if in_external_macro(cx, block.span) { if in_external_macro(cx, expr.span) {
return; 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(); let mut bindings = Vec::new();
for arg in &decl.inputs { for arg in &decl.inputs {
if let PatKind::Binding(_, ident, _) = arg.pat.node { if let PatKind::Binding(_, ident, _) = arg.pat.node {
bindings.push((ident.node, ident.span)) 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)>) { fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) {

View file

@ -114,7 +114,7 @@ impl LateLintPass for StringAdd {
} }
fn is_string(cx: &LateContext, e: &Expr) -> bool { 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 { fn is_add(cx: &LateContext, src: &Expr, target: &Expr) -> bool {

View file

@ -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 lhs1, ref idx1) = lhs1.node {
if let ExprIndex(ref lhs2, ref idx2) = lhs2.node { if let ExprIndex(ref lhs2, ref idx2) = lhs2.node {
if SpanlessEq::new(cx).ignore_fn().eq_expr(lhs1, lhs2) { 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(_)) || if matches!(ty.sty, ty::TySlice(_)) ||
matches!(ty.sty, ty::TyArray(_, _)) || matches!(ty.sty, ty::TyArray(_, _)) ||

View file

@ -91,8 +91,8 @@ impl LateLintPass for Transmute {
let def_id = cx.tcx.expect_def(path_expr.id).def_id(); let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::TRANSMUTE) { if match_def_path(cx, def_id, &paths::TRANSMUTE) {
let from_ty = cx.tcx.expr_ty(&args[0]); let from_ty = cx.tcx.tables().expr_ty(&args[0]);
let to_ty = cx.tcx.expr_ty(e); let to_ty = cx.tcx.tables().expr_ty(e);
match (&from_ty.sty, &to_ty.sty) { match (&from_ty.sty, &to_ty.sty) {
_ if from_ty == to_ty => span_lint( _ if from_ty == to_ty => span_lint(

View file

@ -126,7 +126,7 @@ declare_lint! {
fn check_let_unit(cx: &LateContext, decl: &Decl) { fn check_let_unit(cx: &LateContext, decl: &Decl) {
if let DeclLocal(ref local) = decl.node { 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 { match *bindtype {
ty::TyTuple(slice) if slice.is_empty() => { ty::TyTuple(slice) if slice.is_empty() => {
if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) { 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 { if let ExprBinary(ref cmp, ref left, _) = expr.node {
let op = cmp.node; let op = cmp.node;
if op.is_comparison() { if op.is_comparison() {
let sty = &cx.tcx.expr_ty(left).sty; let sty = &cx.tcx.tables().expr_ty(left).sty;
match *sty { match *sty {
ty::TyTuple(slice) if slice.is_empty() => { ty::TyTuple(slice) if slice.is_empty() => {
let result = match op { let result = match op {
@ -449,7 +449,7 @@ impl LintPass for CastPass {
impl LateLintPass for CastPass { impl LateLintPass for CastPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCast(ref ex, _) = expr.node { 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) { if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
match (cast_from.is_integral(), cast_to.is_integral()) { match (cast_from.is_integral(), cast_to.is_integral()) {
(true, false) => { (true, false) => {
@ -535,7 +535,7 @@ impl LintPass for TypeComplexityPass {
} }
impl LateLintPass 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); self.check_fndecl(cx, decl);
} }
@ -683,7 +683,7 @@ impl LateLintPass for CharLitAsU8 {
if let ExprCast(ref e, _) = expr.node { if let ExprCast(ref e, _) = expr.node {
if let ExprLit(ref l) = e.node { if let ExprLit(ref l) = e.node {
if let LitKind::Char(_) = l.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 \ let msg = "casting character literal to u8. `char`s \
are 4 bytes wide in rust, so casting to u8 \ are 4 bytes wide in rust, so casting to u8 \
truncates them"; truncates them";
@ -791,7 +791,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
use rustc_const_eval::*; use rustc_const_eval::*;
use types::ExtremeType::*; use types::ExtremeType::*;
let ty = &cx.tcx.expr_ty(expr).sty; let ty = &cx.tcx.tables().expr_ty(expr).sty;
match *ty { match *ty {
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (), ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
@ -953,7 +953,7 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
use std::*; use std::*;
if let ExprCast(ref cast_exp, _) = expr.node { 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) => { TyInt(int_ty) => {
Some(match int_ty { Some(match int_ty {
IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)), IntTy::I8 => (FullInt::S(i8::min_value() as i64), FullInt::S(i8::max_value() as i64)),

View file

@ -47,7 +47,7 @@ impl LintPass for UnusedLabel {
} }
impl LateLintPass 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) { if in_macro(cx, span) {
return; return;
} }

View file

@ -368,11 +368,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_expr(e); self.hash_expr(e);
// TODO: _ty // TODO: _ty
} }
ExprClosure(cap, _, ref b, _) => { ExprClosure(cap, _, ref e, _) => {
let c: fn(_, _, _, _) -> _ = ExprClosure; let c: fn(_, _, _, _) -> _ = ExprClosure;
c.hash(&mut self.s); c.hash(&mut self.s);
cap.hash(&mut self.s); cap.hash(&mut self.s);
self.hash_block(b); self.hash_expr(e);
} }
ExprField(ref e, ref f) => { ExprField(ref e, ref f) => {
let c: fn(_, _) -> _ = ExprField; let c: fn(_, _) -> _ = ExprField;

View file

@ -135,7 +135,7 @@ fn has_attr(attrs: &[Attribute]) -> bool {
fn print_decl(cx: &LateContext, decl: &hir::Decl) { fn print_decl(cx: &LateContext, decl: &hir::Decl) {
match decl.node { match decl.node {
hir::DeclLocal(ref local) => { 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:"); println!("pattern:");
print_pat(cx, &local.pat, 0); print_pat(cx, &local.pat, 0);
if let Some(ref e) = local.init { 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) { fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
let ind = " ".repeat(indent); 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); println!("{}+", ind);
match expr.node { match expr.node {
hir::ExprBox(ref e) => { hir::ExprBox(ref e) => {
@ -350,25 +350,25 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
} }
} }
hir::ItemUse(ref path) => println!("{:?}", path.node), hir::ItemUse(ref path) => println!("{:?}", path.node),
hir::ItemStatic(..) => println!("static 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::ItemConst(..) => (), //println!("const item: {:#?}", cx.tcx.opt_lookup_item_type(did)),
hir::ItemFn(..) => { hir::ItemFn(..) => {
let item_ty = cx.tcx.opt_lookup_item_type(did); //let item_ty = cx.tcx.opt_lookup_item_type(did);
println!("function: {:#?}", item_ty); //println!("function: {:#?}", item_ty);
}, },
hir::ItemMod(..) => println!("module"), hir::ItemMod(..) => println!("module"),
hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi), hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
hir::ItemTy(..) => { hir::ItemTy(..) => {
println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did)); //println!("type alias: {:?}", cx.tcx.opt_lookup_item_type(did));
}, },
hir::ItemEnum(..) => { hir::ItemEnum(..) => {
println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did)); //println!("enum definition: {:?}", cx.tcx.opt_lookup_item_type(did));
}, },
hir::ItemStruct(..) => { hir::ItemStruct(..) => {
println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did)); //println!("struct definition: {:?}", cx.tcx.opt_lookup_item_type(did));
}, },
hir::ItemUnion(..) => { hir::ItemUnion(..) => {
println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did)); //println!("union definition: {:?}", cx.tcx.opt_lookup_item_type(did));
}, },
hir::ItemTrait(..) => { hir::ItemTrait(..) => {
println!("trait decl"); println!("trait decl");

View file

@ -429,7 +429,12 @@ pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c
if let Some(node) = enclosing_node { if let Some(node) = enclosing_node {
match node { match node {
Node::NodeBlock(block) => Some(block), 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, _ => None,
} }
} else { } else {
@ -696,8 +701,9 @@ pub fn camel_case_from(s: &str) -> usize {
/// Convenience function to get the return type of a function /// 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::Ty<'tcx> {
let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); 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_def_id = cx.tcx.map.local_def_id(fn_item);
let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); 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 fn_sig.output
} }

View file

@ -36,7 +36,7 @@ impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) { fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
// search for `&vec![_]` expressions where the adjusted type is `&[_]` // search for `&vec![_]` expressions where the adjusted type is `&[_]`
if_let_chain!{[ 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 ty::TypeVariants::TySlice(..) = ty.ty.sty,
let ExprAddrOf(_, ref addressee) = expr.node, let ExprAddrOf(_, ref addressee) = expr.node,
let Some(vec_args) = higher::vec_macro(cx, addressee), let Some(vec_args) = higher::vec_macro(cx, addressee),
@ -48,7 +48,7 @@ impl LateLintPass for Pass {
if_let_chain!{[ if_let_chain!{[
let Some((_, arg, _)) = higher::for_loop(expr), let Some((_, arg, _)) = higher::for_loop(expr),
let Some(vec_args) = higher::vec_macro(cx, arg), 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>:` // report the error around the `vec!` not inside `<std macros>:`
let span = cx.sess().codemap().source_callsite(arg.span); let span = cx.sess().codemap().source_callsite(arg.span);

View file

@ -1,5 +1,4 @@
#![feature(plugin, inclusive_range_syntax)] #![feature(plugin, inclusive_range_syntax)]
#![feature(dotdot_in_tuple_patterns)]
#![plugin(clippy)] #![plugin(clippy)]
#![allow(dead_code, no_effect, unnecessary_operation)] #![allow(dead_code, no_effect, unnecessary_operation)]

View file

@ -1,6 +1,7 @@
#![feature(plugin, never_type)] #![feature(plugin, never_type)]
#![plugin(clippy)] #![plugin(clippy)]
#![deny(diverging_sub_expression)] #![deny(diverging_sub_expression)]
#![allow(match_same_arms, logic_bug)]
#[allow(empty_loop)] #[allow(empty_loop)]
fn diverge() -> ! { loop {} } fn diverge() -> ! { loop {} }
@ -16,8 +17,6 @@ fn main() {
let b = true; let b = true;
b || diverge(); //~ ERROR sub-expression diverges b || diverge(); //~ ERROR sub-expression diverges
b || A.foo(); //~ 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)] #[allow(dead_code, unused_variables)]
@ -26,16 +25,16 @@ fn foobar() {
let x = match 5 { let x = match 5 {
4 => return, 4 => return,
5 => continue, 5 => continue,
6 => (println!("foo"), return), //~ ERROR sub-expression diverges 6 => true || return, //~ ERROR sub-expression diverges
7 => (println!("bar"), continue), //~ ERROR sub-expression diverges 7 => true || continue, //~ ERROR sub-expression diverges
8 => break, 8 => break,
9 => diverge(), 9 => diverge(),
3 => (println!("moo"), diverge()), //~ ERROR sub-expression diverges 3 => true || diverge(), //~ ERROR sub-expression diverges
10 => match 42 { 10 => match 42 {
99 => return, 99 => return,
_ => ((), panic!("boo")), _ => true || panic!("boo"),
}, },
_ => (println!("boo"), break), //~ ERROR sub-expression diverges _ => true || break, //~ ERROR sub-expression diverges
}; };
} }
} }

View file

@ -43,8 +43,8 @@ fn main() {
true || true; //~ERROR equal expressions true || true; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified //~|ERROR this boolean expression can be simplified
let a: u32 = unimplemented!(); let a: u32 = 0;
let b: u32 = unimplemented!(); let b: u32 = 0;
a == b && b == a; //~ERROR equal expressions a == b && b == a; //~ERROR equal expressions
//~|ERROR this boolean expression can be simplified //~|ERROR this boolean expression can be simplified