This commit is contained in:
Oliver Schneider
2017-09-12 14:26:40 +02:00
parent 36cd745640
commit b127ad251f
19 changed files with 246 additions and 246 deletions

30
Cargo.lock generated
View File

@@ -9,8 +9,8 @@ dependencies = [
"quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -61,8 +61,8 @@ name = "cargo_metadata"
version = "0.2.3" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@@ -82,8 +82,8 @@ dependencies = [
"duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -289,22 +289,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.12" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.12" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde_derive_internals" name = "serde_derive_internals"
version = "0.15.1" version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -319,7 +319,7 @@ dependencies = [
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -364,7 +364,7 @@ name = "toml"
version = "0.4.5" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@@ -442,9 +442,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7f61b753dd58ec5d4c735f794dbddde1f28b977f652afbcde89d75bc77902216" "checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34"
"checksum serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2a169fa5384d751ada1da9f3992b81830151a03c875e40dcb37c9fb31aafc68f" "checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58"
"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac"
"checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc" "checksum shared_child 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "099b38928dbe4a0a01fcd8c233183072f14a7d126a34bed05880869be66e14cc"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"

View File

@@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt};
use semver::Version; use semver::Version;
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use syntax::codemap::Span; use syntax::codemap::Span;
use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then}; use utils::{in_macro, match_def_path, paths, snippet_opt, span_lint, span_lint_and_then, opt_def_id};
/// **What it does:** Checks for items annotated with `#[inline(always)]`, /// **What it does:** Checks for items annotated with `#[inline(always)]`,
/// unless the annotated function is empty or simply panics. /// unless the annotated function is empty or simply panics.
@@ -211,8 +211,11 @@ fn is_relevant_expr(tcx: TyCtxt, tables: &ty::TypeckTables, expr: &Expr) -> bool
ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e), ExprRet(Some(ref e)) => is_relevant_expr(tcx, tables, e),
ExprRet(None) | ExprBreak(_, None) => false, ExprRet(None) | ExprBreak(_, None) => false,
ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node { ExprCall(ref path_expr, _) => if let ExprPath(ref qpath) = path_expr.node {
let fun_id = tables.qpath_def(qpath, path_expr.hir_id).def_id(); if let Some(fun_id) = opt_def_id(tables.qpath_def(qpath, path_expr.hir_id)) {
!match_def_path(tcx, fun_id, &paths::BEGIN_PANIC) !match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
} else {
true
}
} else { } else {
true true
}, },

View File

@@ -1,7 +1,7 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::ty; use rustc::ty;
use rustc::hir::*; use rustc::hir::*;
use utils::{is_copy, match_def_path, paths, span_note_and_lint}; use utils::{is_copy, match_def_path, paths, span_note_and_lint, opt_def_id};
/// **What it does:** Checks for calls to `std::mem::drop` with a reference /// **What it does:** Checks for calls to `std::mem::drop` with a reference
/// instead of an owned value. /// instead of an owned value.
@@ -119,8 +119,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let ExprCall(ref path, ref args) = expr.node, let ExprCall(ref path, ref args) = expr.node,
let ExprPath(ref qpath) = path.node, let ExprPath(ref qpath) = path.node,
args.len() == 1, args.len() == 1,
let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)),
], { ], {
let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id();
let lint; let lint;
let msg; let msg;
let arg = &args[0]; let arg = &args[0];

View File

@@ -1,8 +1,8 @@
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::hir::*; use rustc::hir::*;
use rustc::ty; use rustc::ty;
use rustc::lint::*; use rustc::lint::*;
use syntax::ast;
use utils::{get_parent_expr, span_lint, span_note_and_lint}; use utils::{get_parent_expr, span_lint, span_note_and_lint};
/// **What it does:** Checks for a read and a write to the same variable where /// **What it does:** Checks for a read and a write to the same variable where
@@ -65,14 +65,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node { ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => if let ExprPath(ref qpath) = lhs.node {
if let QPath::Resolved(_, ref path) = *qpath { if let QPath::Resolved(_, ref path) = *qpath {
if path.segments.len() == 1 { if path.segments.len() == 1 {
let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id(); if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) {
let mut visitor = ReadVisitor { let mut visitor = ReadVisitor {
cx: cx, cx: cx,
var: var, var: var,
write_expr: expr, write_expr: expr,
last_expr: expr, last_expr: expr,
}; };
check_for_unsequenced_reads(&mut visitor); check_for_unsequenced_reads(&mut visitor);
}
} }
} }
}, },
@@ -280,7 +281,7 @@ fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> St
struct ReadVisitor<'a, 'tcx: 'a> { struct ReadVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
/// The id of the variable we're looking for. /// The id of the variable we're looking for.
var: DefId, var: ast::NodeId,
/// The expressions where the write to the variable occurred (for reporting /// The expressions where the write to the variable occurred (for reporting
/// in the lint). /// in the lint).
write_expr: &'tcx Expr, write_expr: &'tcx Expr,
@@ -297,22 +298,23 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
match expr.node { match expr.node {
ExprPath(ref qpath) => { ExprPath(ref qpath) => {
if let QPath::Resolved(None, ref path) = *qpath { if_let_chain! {[
if path.segments.len() == 1 && self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { let QPath::Resolved(None, ref path) = *qpath,
if is_in_assignment_position(self.cx, expr) { path.segments.len() == 1,
// This is a write, not a read. let def::Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id),
} else { local_id == self.var,
span_note_and_lint( // Check that this is a read, not a write.
self.cx, !is_in_assignment_position(self.cx, expr),
EVAL_ORDER_DEPENDENCE, ], {
expr.span, span_note_and_lint(
"unsequenced read of a variable", self.cx,
self.write_expr.span, EVAL_ORDER_DEPENDENCE,
"whether read occurs before this write depends on evaluation order" expr.span,
); "unsequenced read of a variable",
} self.write_expr.span,
} "whether read occurs before this write depends on evaluation order"
} );
}}
} }
// We're about to descend a closure. Since we don't know when (or // We're about to descend a closure. Since we don't know when (or
// if) the closure will be evaluated, any reads in it might not // if) the closure will be evaluated, any reads in it might not

View File

@@ -5,7 +5,7 @@ use rustc::ty;
use syntax::ast::LitKind; use syntax::ast::LitKind;
use syntax::symbol::InternedString; use syntax::symbol::InternedString;
use utils::paths; use utils::paths;
use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty}; use utils::{is_expn_of, match_def_path, match_type, resolve_node, span_lint, walk_ptrs_ty, opt_def_id};
/// **What it does:** Checks for the use of `format!("string literal with no /// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string. /// argument")` and `format!("{}", foo)` where `foo` is a string.
@@ -47,7 +47,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if_let_chain!{[ if_let_chain!{[
let ExprPath(ref qpath) = fun.node, let ExprPath(ref qpath) = fun.node,
args.len() == 2, args.len() == 2,
match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::FMT_ARGUMENTS_NEWV1), let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)),
match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1),
// ensure the format string is `"{..}"` with only one argument and no text // ensure the format string is `"{..}"` with only one argument and no text
check_static_str(cx, &args[0]), check_static_str(cx, &args[0]),
// ensure the format argument is `{}` ie. Display with no fancy option // ensure the format argument is `{}` ie. Display with no fancy option
@@ -128,7 +129,8 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
let ExprCall(_, ref args) = exprs[0].node, let ExprCall(_, ref args) = exprs[0].node,
args.len() == 2, args.len() == 2,
let ExprPath(ref qpath) = args[1].node, let ExprPath(ref qpath) = args[1].node,
match_def_path(cx.tcx, resolve_node(cx, qpath, args[1].hir_id).def_id(), &paths::DISPLAY_FMT_METHOD), let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, args[1].hir_id)),
match_def_path(cx.tcx, fun_def_id, &paths::DISPLAY_FMT_METHOD),
], { ], {
let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0])); let ty = walk_ptrs_ty(cx.tables.pat_ty(&pat[0]));

View File

@@ -2,6 +2,7 @@ use rustc::hir::intravisit;
use rustc::hir; use rustc::hir;
use rustc::lint::*; use rustc::lint::*;
use rustc::ty; use rustc::ty;
use rustc::hir::def::Def;
use std::collections::HashSet; use std::collections::HashSet;
use syntax::ast; use syntax::ast;
use syntax::abi::Abi; use syntax::abi::Abi;
@@ -166,9 +167,9 @@ impl<'a, 'tcx> Functions {
} }
} }
fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<hir::def_id::DefId> { fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<ast::NodeId> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) { if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) {
Some(def_id) Some(id)
} else { } else {
None None
} }
@@ -176,7 +177,7 @@ fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<hir::def_id::DefId> {
struct DerefVisitor<'a, 'tcx: 'a> { struct DerefVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
ptrs: HashSet<hir::def_id::DefId>, ptrs: HashSet<ast::NodeId>,
tables: &'a ty::TypeckTables<'tcx>, tables: &'a ty::TypeckTables<'tcx>,
} }
@@ -216,14 +217,15 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
fn check_arg(&self, ptr: &hir::Expr) { fn check_arg(&self, ptr: &hir::Expr) {
if let hir::ExprPath(ref qpath) = ptr.node { if let hir::ExprPath(ref qpath) = ptr.node {
let def = self.cx.tables.qpath_def(qpath, ptr.hir_id); if let Def::Local(id) = self.cx.tables.qpath_def(qpath, ptr.hir_id) {
if self.ptrs.contains(&def.def_id()) { if self.ptrs.contains(&id) {
span_lint( span_lint(
self.cx, self.cx,
NOT_UNSAFE_PTR_ARG_DEREF, NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span, ptr.span,
"this public function dereferences a raw pointer but is not marked `unsafe`", "this public function dereferences a raw pointer but is not marked `unsafe`",
); );
}
} }
} }
} }

View File

@@ -1,6 +1,8 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir; use rustc::hir;
use rustc::hir::BindingAnnotation; use rustc::hir::BindingAnnotation;
use rustc::hir::def::Def;
use syntax::ast;
use utils::{snippet, span_lint_and_then}; use utils::{snippet, span_lint_and_then};
/// **What it does:** Checks for variable declarations immediately followed by a /// **What it does:** Checks for variable declarations immediately followed by a
@@ -65,19 +67,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
let Some(expr) = it.peek(), let Some(expr) = it.peek(),
let hir::StmtDecl(ref decl, _) = stmt.node, let hir::StmtDecl(ref decl, _) = stmt.node,
let hir::DeclLocal(ref decl) = decl.node, let hir::DeclLocal(ref decl) = decl.node,
let hir::PatKind::Binding(mode, def_id, ref name, None) = decl.pat.node, let hir::PatKind::Binding(mode, canonical_id, ref name, None) = decl.pat.node,
let hir::StmtExpr(ref if_, _) = expr.node, let hir::StmtExpr(ref if_, _) = expr.node,
let hir::ExprIf(ref cond, ref then, ref else_) = if_.node, let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
!used_in_expr(cx, def_id, cond), !used_in_expr(cx, canonical_id, cond),
let hir::ExprBlock(ref then) = then.node, let hir::ExprBlock(ref then) = then.node,
let Some(value) = check_assign(cx, def_id, &*then), let Some(value) = check_assign(cx, canonical_id, &*then),
!used_in_expr(cx, def_id, value), !used_in_expr(cx, canonical_id, value),
], { ], {
let span = stmt.span.to(if_.span); let span = stmt.span.to(if_.span);
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ { let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
if let hir::ExprBlock(ref else_) = else_.node { if let hir::ExprBlock(ref else_) = else_.node {
if let Some(default) = check_assign(cx, def_id, else_) { if let Some(default) = check_assign(cx, canonical_id, else_) {
(else_.stmts.len() > 1, default) (else_.stmts.len() > 1, default)
} else if let Some(ref default) = decl.init { } else if let Some(ref default) = decl.init {
(true, &**default) (true, &**default)
@@ -130,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
struct UsedVisitor<'a, 'tcx: 'a> { struct UsedVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
id: hir::def_id::DefId, id: ast::NodeId,
used: bool, used: bool,
} }
@@ -138,7 +140,8 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) { fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if_let_chain! {[ if_let_chain! {[
let hir::ExprPath(ref qpath) = expr.node, let hir::ExprPath(ref qpath) = expr.node,
self.id == self.cx.tables.qpath_def(qpath, expr.hir_id).def_id(), let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id),
self.id == local_id,
], { ], {
self.used = true; self.used = true;
return; return;
@@ -152,7 +155,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
fn check_assign<'a, 'tcx>( fn check_assign<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
decl: hir::def_id::DefId, decl: ast::NodeId,
block: &'tcx hir::Block, block: &'tcx hir::Block,
) -> Option<&'tcx hir::Expr> { ) -> Option<&'tcx hir::Expr> {
if_let_chain! {[ if_let_chain! {[
@@ -161,7 +164,8 @@ fn check_assign<'a, 'tcx>(
let hir::StmtSemi(ref expr, _) = expr.node, let hir::StmtSemi(ref expr, _) = expr.node,
let hir::ExprAssign(ref var, ref value) = expr.node, let hir::ExprAssign(ref var, ref value) = expr.node,
let hir::ExprPath(ref qpath) = var.node, let hir::ExprPath(ref qpath) = var.node,
decl == cx.tables.qpath_def(qpath, var.hir_id).def_id(), let Def::Local(local_id) = cx.tables.qpath_def(qpath, var.hir_id),
decl == local_id,
], { ], {
let mut v = UsedVisitor { let mut v = UsedVisitor {
cx: cx, cx: cx,
@@ -183,7 +187,7 @@ fn check_assign<'a, 'tcx>(
None None
} }
fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: hir::def_id::DefId, expr: &'tcx hir::Expr) -> bool { fn used_in_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, id: ast::NodeId, expr: &'tcx hir::Expr) -> bool {
let mut v = UsedVisitor { let mut v = UsedVisitor {
cx: cx, cx: cx,
id: id, id: id,

View File

@@ -2,7 +2,6 @@ use itertools::Itertools;
use reexport::*; use reexport::*;
use rustc::hir::*; use rustc::hir::*;
use rustc::hir::def::Def; use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor}; use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt}; use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt};
use rustc::lint::*; use rustc::lint::*;
@@ -594,13 +593,14 @@ fn check_for_loop<'a, 'tcx>(
detect_manual_memcpy(cx, pat, arg, body, expr); detect_manual_memcpy(cx, pat, arg, body, expr);
} }
fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> bool { fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> bool {
if_let_chain! {[ if_let_chain! {[
let ExprPath(ref qpath) = expr.node, let ExprPath(ref qpath) = expr.node,
let QPath::Resolved(None, ref path) = *qpath, let QPath::Resolved(None, ref path) = *qpath,
path.segments.len() == 1, path.segments.len() == 1,
let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id),
// our variable! // our variable!
cx.tables.qpath_def(qpath, expr.hir_id).def_id() == var local_id == var
], { ], {
return true; return true;
}} }}
@@ -644,8 +644,8 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty) -> bool {
is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE) is_slice || match_type(cx, ty, &paths::VEC) || match_type(cx, ty, &paths::VEC_DEQUE)
} }
fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> Option<FixedOffsetVar> { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: ast::NodeId) -> Option<FixedOffsetVar> {
fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: DefId) -> Option<String> { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: ast::NodeId) -> Option<String> {
match e.node { match e.node {
ExprLit(ref l) => match l.node { ExprLit(ref l) => match l.node {
ast::LitKind::Int(x, _ty) => Some(x.to_string()), ast::LitKind::Int(x, _ty) => Some(x.to_string()),
@@ -700,12 +700,12 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var:
fn get_indexed_assignments<'a, 'tcx>( fn get_indexed_assignments<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
body: &Expr, body: &Expr,
var: DefId, var: ast::NodeId,
) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { ) -> Vec<(FixedOffsetVar, FixedOffsetVar)> {
fn get_assignment<'a, 'tcx>( fn get_assignment<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>, cx: &LateContext<'a, 'tcx>,
e: &Expr, e: &Expr,
var: DefId, var: ast::NodeId,
) -> Option<(FixedOffsetVar, FixedOffsetVar)> { ) -> Option<(FixedOffsetVar, FixedOffsetVar)> {
if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node { if let Expr_::ExprAssign(ref lhs, ref rhs) = e.node {
match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) { match (get_fixed_offset_var(cx, lhs, var), get_fixed_offset_var(cx, rhs, var)) {
@@ -759,7 +759,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
}) = higher::range(arg) }) = higher::range(arg)
{ {
// the var must be a single name // the var must be a single name
if let PatKind::Binding(_, def_id, _, _) = pat.node { if let PatKind::Binding(_, canonical_id, _, _) = pat.node {
let print_sum = |arg1: &Offset, arg2: &Offset| -> String { let print_sum = |arg1: &Offset, arg2: &Offset| -> String {
match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) {
("0", _, "0", _) => "".into(), ("0", _, "0", _) => "".into(),
@@ -802,7 +802,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
// The only statements in the for loops can be indexed assignments from // The only statements in the for loops can be indexed assignments from
// indexed retrievals. // indexed retrievals.
let manual_copies = get_indexed_assignments(cx, body, def_id); let manual_copies = get_indexed_assignments(cx, body, canonical_id);
let big_sugg = manual_copies let big_sugg = manual_copies
.into_iter() .into_iter()
@@ -852,10 +852,10 @@ fn check_for_loop_range<'a, 'tcx>(
}) = higher::range(arg) }) = higher::range(arg)
{ {
// the var must be a single name // the var must be a single name
if let PatKind::Binding(_, def_id, ref ident, _) = pat.node { if let PatKind::Binding(_, canonical_id, ref ident, _) = pat.node {
let mut visitor = VarVisitor { let mut visitor = VarVisitor {
cx: cx, cx: cx,
var: def_id, var: canonical_id,
indexed: HashMap::new(), indexed: HashMap::new(),
referenced: HashSet::new(), referenced: HashSet::new(),
nonindex: false, nonindex: false,
@@ -1298,15 +1298,15 @@ impl<'tcx> Visitor<'tcx> for UsedVisitor {
} }
} }
struct DefIdUsedVisitor<'a, 'tcx: 'a> { struct LocalUsedVisitor <'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
def_id: DefId, local: ast::NodeId,
used: bool, used: bool,
} }
impl<'a, 'tcx: 'a> Visitor<'tcx> for DefIdUsedVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) { fn visit_expr(&mut self, expr: &'tcx Expr) {
if same_var(self.cx, expr, self.def_id) { if same_var(self.cx, expr, self.local) {
self.used = true; self.used = true;
} else { } else {
walk_expr(self, expr); walk_expr(self, expr);
@@ -1322,7 +1322,7 @@ struct VarVisitor<'a, 'tcx: 'a> {
/// context reference /// context reference
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
/// var name to look for as index /// var name to look for as index
var: DefId, var: ast::NodeId,
/// indexed variables, the extend is `None` for global /// indexed variables, the extend is `None` for global
indexed: HashMap<Name, Option<region::Scope>>, indexed: HashMap<Name, Option<region::Scope>>,
/// Any names that are used outside an index operation. /// Any names that are used outside an index operation.
@@ -1344,9 +1344,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
seqvar.segments.len() == 1, seqvar.segments.len() == 1,
], { ], {
let index_used = same_var(self.cx, idx, self.var) || { let index_used = same_var(self.cx, idx, self.var) || {
let mut used_visitor = DefIdUsedVisitor { let mut used_visitor = LocalUsedVisitor {
cx: self.cx, cx: self.cx,
def_id: self.var, local: self.var,
used: false, used: false,
}; };
walk_expr(&mut used_visitor, idx); walk_expr(&mut used_visitor, idx);
@@ -1356,9 +1356,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if index_used { if index_used {
let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id); let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id);
match def { match def {
Def::Local(..) | Def::Upvar(..) => { Def::Local(node_id) | Def::Upvar(node_id, ..) => {
let def_id = def.def_id();
let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes");
let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id); let hir_id = self.cx.tcx.hir.node_to_hir_id(node_id);
let parent_id = self.cx.tcx.hir.get_parent(expr.id); let parent_id = self.cx.tcx.hir.get_parent(expr.id);
@@ -1381,8 +1379,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
let ExprPath(ref qpath) = expr.node, let ExprPath(ref qpath) = expr.node,
let QPath::Resolved(None, ref path) = *qpath, let QPath::Resolved(None, ref path) = *qpath,
path.segments.len() == 1, path.segments.len() == 1,
let Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id),
], { ], {
if self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var { if local_id == self.var {
// we are not indexing anything, record that // we are not indexing anything, record that
self.nonindex = true; self.nonindex = true;
} else { } else {
@@ -1672,11 +1671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> { fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
if let ExprPath(ref qpath) = expr.node { if let ExprPath(ref qpath) = expr.node {
let path_res = cx.tables.qpath_def(qpath, expr.hir_id); let path_res = cx.tables.qpath_def(qpath, expr.hir_id);
if let Def::Local(def_id) = path_res { if let Def::Local(node_id) = path_res {
let node_id = cx.tcx
.hir
.as_local_node_id(def_id)
.expect("That DefId should be valid");
return Some(node_id); return Some(node_id);
} }
} }

View File

@@ -1,6 +1,6 @@
use rustc::lint::*; use rustc::lint::*;
use rustc::hir::{Expr, ExprCall, ExprPath}; use rustc::hir::{Expr, ExprCall, ExprPath};
use utils::{match_def_path, paths, span_lint}; use utils::{match_def_path, paths, span_lint, opt_def_id};
/// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is /// **What it does:** Checks for usage of `std::mem::forget(t)` where `t` is
/// `Drop`. /// `Drop`.
@@ -32,15 +32,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprCall(ref path_expr, ref args) = e.node { if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(ref qpath) = path_expr.node { if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) {
if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) { if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tables.expr_ty(&args[0]); let forgot_ty = cx.tables.expr_ty(&args[0]);
if match forgot_ty.ty_adt_def() { if match forgot_ty.ty_adt_def() {
Some(def) => def.has_dtor(cx.tcx), Some(def) => def.has_dtor(cx.tcx),
_ => false, _ => false,
} { } {
span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type");
}
} }
} }
} }

View File

@@ -2,7 +2,7 @@ use consts::{constant_simple, Constant};
use rustc::lint::*; use rustc::lint::*;
use rustc::hir::*; use rustc::hir::*;
use std::cmp::{Ordering, PartialOrd}; use std::cmp::{Ordering, PartialOrd};
use utils::{match_def_path, paths, span_lint}; use utils::{match_def_path, paths, span_lint, opt_def_id};
/// **What it does:** Checks for expressions where `std::cmp::min` and `max` are /// **What it does:** Checks for expressions where `std::cmp::min` and `max` are
/// used to clamp values, but switched so that the result is constant. /// used to clamp values, but switched so that the result is constant.
@@ -60,15 +60,15 @@ enum MinMax {
fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> { fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
if let ExprCall(ref path, ref args) = expr.node { if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(ref qpath) = path.node { if let ExprPath(ref qpath) = path.node {
let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id(); opt_def_id(cx.tables.qpath_def(qpath, path.hir_id)).and_then(|def_id| {
if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) {
if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { fetch_const(cx, args, MinMax::Min)
fetch_const(cx, args, MinMax::Min) } else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) {
} else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) { fetch_const(cx, args, MinMax::Max)
fetch_const(cx, args, MinMax::Max) } else {
} else { None
None }
} })
} else { } else {
None None
} }

View File

@@ -574,11 +574,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
/// Test whether `def` is a variable defined outside a macro. /// Test whether `def` is a variable defined outside a macro.
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool { fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
match *def { match *def {
def::Def::Local(def_id) | def::Def::Upvar(def_id, _, _) => { def::Def::Local(id) | def::Def::Upvar(id, _, _) => {
let id = cx.tcx
.hir
.as_local_node_id(def_id)
.expect("local variables should be found in the same crate");
!in_macro(cx.tcx.hir.span(id)) !in_macro(cx.tcx.hir.span(id))
}, },
_ => false, _ => false,

View File

@@ -1,6 +1,5 @@
use rustc::hir::*; use rustc::hir::*;
use rustc::hir::intravisit::FnKind; use rustc::hir::intravisit::FnKind;
use rustc::hir::def_id::DefId;
use rustc::lint::*; use rustc::lint::*;
use rustc::ty::{self, TypeFoldable}; use rustc::ty::{self, TypeFoldable};
use rustc::traits; use rustc::traits;
@@ -129,8 +128,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
!implements_trait(cx, ty, asref_trait, &[]), !implements_trait(cx, ty, asref_trait, &[]),
!implements_borrow_trait, !implements_borrow_trait,
let PatKind::Binding(mode, defid, ..) = arg.pat.node, let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node,
!moved_vars.contains(&defid), !moved_vars.contains(&canonical_id),
], { ], {
// Note: `toplevel_ref_arg` warns if `BindByRef` // Note: `toplevel_ref_arg` warns if `BindByRef`
if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut { if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut {
@@ -139,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
// Suggestion logic // Suggestion logic
let sugg = |db: &mut DiagnosticBuilder| { let sugg = |db: &mut DiagnosticBuilder| {
let deref_span = spans_need_deref.get(&defid); let deref_span = spans_need_deref.get(&canonical_id);
if_let_chain! {[ if_let_chain! {[
match_type(cx, ty, &paths::VEC), match_type(cx, ty, &paths::VEC),
let TyPath(QPath::Resolved(_, ref path)) = input.node, let TyPath(QPath::Resolved(_, ref path)) = input.node,
@@ -186,11 +185,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
struct MovedVariablesCtxt<'a, 'tcx: 'a> { struct MovedVariablesCtxt<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>, cx: &'a LateContext<'a, 'tcx>,
moved_vars: HashSet<DefId>, moved_vars: HashSet<NodeId>,
/// Spans which need to be prefixed with `*` for dereferencing the /// Spans which need to be prefixed with `*` for dereferencing the
/// suggested additional /// suggested additional
/// reference. /// reference.
spans_need_deref: HashMap<DefId, HashSet<Span>>, spans_need_deref: HashMap<NodeId, HashSet<Span>>,
} }
impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> { impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
@@ -205,12 +204,9 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt<'tcx>) { fn move_common(&mut self, _consume_id: NodeId, _span: Span, cmt: mc::cmt<'tcx>) {
let cmt = unwrap_downcast_or_interior(cmt); let cmt = unwrap_downcast_or_interior(cmt);
if_let_chain! {[ if let mc::Categorization::Local(vid) = cmt.cat {
let mc::Categorization::Local(vid) = cmt.cat, self.moved_vars.insert(vid);
let Some(def_id) = self.cx.tcx.hir.opt_local_def_id(vid), }
], {
self.moved_vars.insert(def_id);
}}
} }
fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) { fn non_moving_pat(&mut self, matched_pat: &Pat, cmt: mc::cmt<'tcx>) {
@@ -218,7 +214,6 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
if_let_chain! {[ if_let_chain! {[
let mc::Categorization::Local(vid) = cmt.cat, let mc::Categorization::Local(vid) = cmt.cat,
let Some(def_id) = self.cx.tcx.hir.opt_local_def_id(vid),
], { ], {
let mut id = matched_pat.id; let mut id = matched_pat.id;
loop { loop {
@@ -235,7 +230,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
// `match` and `if let` // `match` and `if let`
if let ExprMatch(ref c, ..) = e.node { if let ExprMatch(ref c, ..) = e.node {
self.spans_need_deref self.spans_need_deref
.entry(def_id) .entry(vid)
.or_insert_with(HashSet::new) .or_insert_with(HashSet::new)
.insert(c.span); .insert(c.span);
} }
@@ -248,7 +243,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
let DeclLocal(ref local) = decl.node, let DeclLocal(ref local) = decl.node,
], { ], {
self.spans_need_deref self.spans_need_deref
.entry(def_id) .entry(vid)
.or_insert_with(HashSet::new) .or_insert_with(HashSet::new)
.insert(local.init .insert(local.init
.as_ref() .as_ref()

View File

@@ -1,7 +1,7 @@
use rustc::hir::*; use rustc::hir::*;
use rustc::lint::*; use rustc::lint::*;
use syntax::ast::LitKind; use syntax::ast::LitKind;
use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint}; use utils::{is_direct_expn_of, match_def_path, paths, resolve_node, span_lint, opt_def_id};
/// **What it does:** Checks for missing parameters in `panic!`. /// **What it does:** Checks for missing parameters in `panic!`.
/// ///
@@ -40,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let ExprCall(ref fun, ref params) = ex.node, let ExprCall(ref fun, ref params) = ex.node,
params.len() == 2, params.len() == 2,
let ExprPath(ref qpath) = fun.node, let ExprPath(ref qpath) = fun.node,
match_def_path(cx.tcx, resolve_node(cx, qpath, fun.hir_id).def_id(), &paths::BEGIN_PANIC), let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)),
match_def_path(cx.tcx, fun_def_id, &paths::BEGIN_PANIC),
let ExprLit(ref lit) = params[0].node, let ExprLit(ref lit) = params[0].node,
is_direct_expn_of(expr.span, "panic").is_some(), is_direct_expn_of(expr.span, "panic").is_some(),
let LitKind::Str(ref string, _) = lit.node, let LitKind::Str(ref string, _) = lit.node,

View File

@@ -1,7 +1,7 @@
use rustc::hir::*; use rustc::hir::*;
use rustc::hir::map::Node::{NodeImplItem, NodeItem}; use rustc::hir::map::Node::{NodeImplItem, NodeItem};
use rustc::lint::*; use rustc::lint::*;
use utils::paths; use utils::{paths, opt_def_id};
use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint}; use utils::{is_expn_of, match_def_path, match_path, resolve_node, span_lint};
use format::get_argument_fmtstr_parts; use format::get_argument_fmtstr_parts;
@@ -72,9 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if_let_chain! {[ if_let_chain! {[
let ExprCall(ref fun, ref args) = expr.node, let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(ref qpath) = fun.node, let ExprPath(ref qpath) = fun.node,
let Some(fun_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id)),
], { ], {
let fun = resolve_node(cx, qpath, fun.hir_id);
let fun_id = fun.def_id();
// Search for `std::io::_print(..)` which is unique in a // Search for `std::io::_print(..)` which is unique in a
// `print!` expansion. // `print!` expansion.
@@ -96,9 +95,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
args.len() == 1, args.len() == 1,
let ExprCall(ref args_fun, ref args_args) = args[0].node, let ExprCall(ref args_fun, ref args_args) = args[0].node,
let ExprPath(ref qpath) = args_fun.node, let ExprPath(ref qpath) = args_fun.node,
match_def_path(cx.tcx, let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)),
resolve_node(cx, qpath, args_fun.hir_id).def_id(), match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1),
&paths::FMT_ARGUMENTS_NEWV1),
args_args.len() == 2, args_args.len() == 2,
let ExprAddrOf(_, ref match_expr) = args_args[1].node, let ExprAddrOf(_, ref match_expr) = args_args[1].node,
let ExprMatch(ref args, _, _) = match_expr.node, let ExprMatch(ref args, _, _) = match_expr.node,
@@ -125,10 +123,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)` // `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) { else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
if let ExprPath(ref qpath) = args[1].node { if let ExprPath(ref qpath) = args[1].node {
let def_id = cx.tables.qpath_def(qpath, args[1].hir_id).def_id(); if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, args[1].hir_id)) {
if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) && is_expn_of(expr.span, "panic").is_none() {
is_expn_of(expr.span, "panic").is_none() { span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting"); }
} }
} }
} }

View File

@@ -9,7 +9,7 @@ use std::error::Error;
use syntax::ast::{LitKind, NodeId}; use syntax::ast::{LitKind, NodeId};
use syntax::codemap::{BytePos, Span}; use syntax::codemap::{BytePos, Span};
use syntax::symbol::InternedString; use syntax::symbol::InternedString;
use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint}; use utils::{is_expn_of, match_def_path, match_type, paths, span_help_and_lint, span_lint, opt_def_id};
/// **What it does:** Checks [regex](https://crates.io/crates/regex) creation /// **What it does:** Checks [regex](https://crates.io/crates/regex) creation
/// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct /// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct
@@ -116,8 +116,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let ExprCall(ref fun, ref args) = expr.node, let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(ref qpath) = fun.node, let ExprPath(ref qpath) = fun.node,
args.len() == 1, args.len() == 1,
let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, fun.hir_id)),
], { ], {
let def_id = cx.tables.qpath_def(qpath, fun.hir_id).def_id();
if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) || if match_def_path(cx.tcx, def_id, &paths::REGEX_NEW) ||
match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) { match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) {
check_regex(cx, &args[0], true); check_regex(cx, &args[0], true);

View File

@@ -2,7 +2,7 @@ use rustc::lint::*;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::hir::*; use rustc::hir::*;
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then}; use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
use utils::sugg; use utils::{sugg, opt_def_id};
/// **What it does:** Checks for transmutes that can't ever be correct on any /// **What it does:** Checks for transmutes that can't ever be correct on any
/// architecture. /// architecture.
@@ -88,97 +88,98 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprCall(ref path_expr, ref args) = e.node { if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(ref qpath) = path_expr.node { if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id(); if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path_expr.hir_id)) {
if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) { if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) {
let from_ty = cx.tables.expr_ty(&args[0]); let from_ty = cx.tables.expr_ty(&args[0]);
let to_ty = cx.tables.expr_ty(e); let to_ty = cx.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(
cx, cx,
USELESS_TRANSMUTE, USELESS_TRANSMUTE,
e.span, e.span,
&format!("transmute from a type (`{}`) to itself", from_ty), &format!("transmute from a type (`{}`) to itself", from_ty),
),
(&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then(
cx,
USELESS_TRANSMUTE,
e.span,
"transmute from a reference to a pointer",
|db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
let sugg = if ptr_ty == rty {
arg.as_ty(to_ty)
} else {
arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty)
};
db.span_suggestion(e.span, "try", sugg.to_string());
},
),
(&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then(
cx,
USELESS_TRANSMUTE,
e.span,
"transmute from an integer to a pointer",
|db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string());
},
),
(&ty::TyFloat(_), &ty::TyRef(..)) |
(&ty::TyFloat(_), &ty::TyRawPtr(_)) |
(&ty::TyChar, &ty::TyRef(..)) |
(&ty::TyChar, &ty::TyRawPtr(_)) => span_lint(
cx,
WRONG_TRANSMUTE,
e.span,
&format!("transmute from a `{}` to a pointer", from_ty),
),
(&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!(
"transmute from a type (`{}`) to the type that it points to (`{}`)",
from_ty,
to_ty
), ),
), (&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then(
(_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint( cx,
cx, USELESS_TRANSMUTE,
CROSSPOINTER_TRANSMUTE, e.span,
e.span, "transmute from a reference to a pointer",
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty), |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
), let sugg = if ptr_ty == rty {
(&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then( arg.as_ty(to_ty)
cx, } else {
TRANSMUTE_PTR_TO_REF, arg.as_ty(cx.tcx.mk_ptr(rty)).as_ty(to_ty)
e.span, };
&format!(
"transmute from a pointer type (`{}`) to a reference type \ db.span_suggestion(e.span, "try", sugg.to_string());
(`{}`)", },
from_ty,
to_ty
), ),
|db| { (&ty::TyInt(_), &ty::TyRawPtr(_)) | (&ty::TyUint(_), &ty::TyRawPtr(_)) => span_lint_and_then(
let arg = sugg::Sugg::hir(cx, &args[0], ".."); cx,
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable { USELESS_TRANSMUTE,
("&mut *", "*mut") e.span,
} else { "transmute from an integer to a pointer",
("&*", "*const") |db| if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) {
}; db.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()).to_string());
},
),
(&ty::TyFloat(_), &ty::TyRef(..)) |
(&ty::TyFloat(_), &ty::TyRawPtr(_)) |
(&ty::TyChar, &ty::TyRef(..)) |
(&ty::TyChar, &ty::TyRawPtr(_)) => span_lint(
cx,
WRONG_TRANSMUTE,
e.span,
&format!("transmute from a `{}` to a pointer", from_ty),
),
(&ty::TyRawPtr(from_ptr), _) if from_ptr.ty == to_ty => span_lint(
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!(
"transmute from a type (`{}`) to the type that it points to (`{}`)",
from_ty,
to_ty
),
),
(_, &ty::TyRawPtr(to_ptr)) if to_ptr.ty == from_ty => span_lint(
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to a pointer to that type (`{}`)", from_ty, to_ty),
),
(&ty::TyRawPtr(from_pty), &ty::TyRef(_, to_rty)) => span_lint_and_then(
cx,
TRANSMUTE_PTR_TO_REF,
e.span,
&format!(
"transmute from a pointer type (`{}`) to a reference type \
(`{}`)",
from_ty,
to_ty
),
|db| {
let arg = sugg::Sugg::hir(cx, &args[0], "..");
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
("&mut *", "*mut")
} else {
("&*", "*const")
};
let arg = if from_pty.ty == to_rty.ty { let arg = if from_pty.ty == to_rty.ty {
arg arg
} else { } else {
arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty))) arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty)))
}; };
db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string()); db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
}, },
), ),
_ => return, _ => return,
}; };
}
} }
} }
} }

View File

@@ -6,7 +6,7 @@
use rustc::hir; use rustc::hir;
use rustc::lint::LateContext; use rustc::lint::LateContext;
use syntax::ast; use syntax::ast;
use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node}; use utils::{is_expn_of, match_def_path, match_qpath, paths, resolve_node, opt_def_id};
/// Convert a hir binary operator to the corresponding `ast` type. /// Convert a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOp_) -> ast::BinOpKind { pub fn binop(op: hir::BinOp_) -> ast::BinOpKind {
@@ -181,13 +181,13 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e
let hir::ExprCall(ref fun, ref args) = expr.node, let hir::ExprCall(ref fun, ref args) = expr.node,
let hir::ExprPath(ref path) = fun.node, let hir::ExprPath(ref path) = fun.node,
is_expn_of(fun.span, "vec").is_some(), is_expn_of(fun.span, "vec").is_some(),
let Some(fun_def_id) = opt_def_id(resolve_node(cx, path, fun.hir_id)),
], { ], {
let fun_def = resolve_node(cx, path, fun.hir_id); return if match_def_path(cx.tcx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
return if match_def_path(cx.tcx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
// `vec![elem; size]` case // `vec![elem; size]` case
Some(VecArgs::Repeat(&args[0], &args[1])) Some(VecArgs::Repeat(&args[0], &args[1]))
} }
else if match_def_path(cx.tcx, fun_def.def_id(), &paths::SLICE_INTO_VEC) && args.len() == 1 { else if match_def_path(cx.tcx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
// `vec![a, b, c]` case // `vec![a, b, c]` case
if_let_chain!{[ if_let_chain!{[
let hir::ExprBox(ref boxed) = args[0].node, let hir::ExprBox(ref boxed) = args[0].node,

View File

@@ -360,7 +360,8 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
} }
match item.node { match item.node {
hir::ItemExternCrate(ref _renamed_from) => { hir::ItemExternCrate(ref _renamed_from) => {
if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(item.hir_id) { let def_id = cx.tcx.hir.local_def_id(item.id);
if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(def_id) {
let source = cx.tcx.used_crate_source(crate_id); let source = cx.tcx.used_crate_source(crate_id);
if let Some(ref src) = source.dylib { if let Some(ref src) = source.dylib {
println!("extern crate dylib source: {:?}", src.0); println!("extern crate dylib source: {:?}", src.0);

View File

@@ -950,12 +950,10 @@ pub fn opt_def_id(def: Def) -> Option<DefId> {
Def::Method(id) | Def::Method(id) |
Def::Const(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::AssociatedConst(id) |
Def::Local(id) |
Def::Upvar(id, ..) |
Def::Macro(id, ..) | Def::Macro(id, ..) |
Def::GlobalAsm(id) => Some(id), Def::GlobalAsm(id) => Some(id),
Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None, Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
} }
} }
@@ -991,7 +989,8 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> {
match_qpath(path, &paths::RESULT_OK[1..]), match_qpath(path, &paths::RESULT_OK[1..]),
let PatKind::Binding(_, defid, _, None) = pat[0].node, let PatKind::Binding(_, defid, _, None) = pat[0].node,
let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node, let ExprPath(QPath::Resolved(None, ref path)) = arm.body.node,
path.def.def_id() == defid, let Def::Local(lid) = path.def,
lid == defid,
], { ], {
return true; return true;
}} }}