This commit is contained in:
Oliver Schneider 2017-09-12 14:26:40 +02:00
parent 36cd745640
commit b127ad251f
No known key found for this signature in database
GPG Key ID: A69F8D225B3AD7D9
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)",
"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)",
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 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.14 (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)",
]
@ -61,8 +61,8 @@ name = "cargo_metadata"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 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.14 (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)",
"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)",
"serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 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.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -289,22 +289,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.12"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.12"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
]
[[package]]
name = "serde_derive_internals"
version = "0.15.1"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
"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)",
"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]]
@ -364,7 +364,7 @@ name = "toml"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
@ -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 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 serde 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "7f61b753dd58ec5d4c735f794dbddde1f28b977f652afbcde89d75bc77902216"
"checksum serde_derive 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "2a169fa5384d751ada1da9f3992b81830151a03c875e40dcb37c9fb31aafc68f"
"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
"checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34"
"checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c"
"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 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"

View File

@ -7,7 +7,7 @@ use rustc::ty::{self, TyCtxt};
use semver::Version;
use syntax::ast::{Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
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)]`,
/// 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(None) | ExprBreak(_, None) => false,
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();
!match_def_path(tcx, fun_id, &paths::BEGIN_PANIC)
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)
} else {
true
}
} else {
true
},

View File

@ -1,7 +1,7 @@
use rustc::lint::*;
use rustc::ty;
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
/// 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 ExprPath(ref qpath) = path.node,
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 msg;
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::*;
use rustc::ty;
use rustc::lint::*;
use syntax::ast;
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
@ -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 {
if let QPath::Resolved(_, ref path) = *qpath {
if path.segments.len() == 1 {
let var = cx.tables.qpath_def(qpath, lhs.hir_id).def_id();
let mut visitor = ReadVisitor {
cx: cx,
var: var,
write_expr: expr,
last_expr: expr,
};
check_for_unsequenced_reads(&mut visitor);
if let def::Def::Local(var) = cx.tables.qpath_def(qpath, lhs.hir_id) {
let mut visitor = ReadVisitor {
cx: cx,
var: var,
write_expr: expr,
last_expr: expr,
};
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> {
cx: &'a LateContext<'a, 'tcx>,
/// 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
/// in the lint).
write_expr: &'tcx Expr,
@ -297,22 +298,23 @@ impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
match expr.node {
ExprPath(ref qpath) => {
if let QPath::Resolved(None, ref path) = *qpath {
if path.segments.len() == 1 && self.cx.tables.qpath_def(qpath, expr.hir_id).def_id() == self.var {
if is_in_assignment_position(self.cx, expr) {
// This is a write, not a read.
} else {
span_note_and_lint(
self.cx,
EVAL_ORDER_DEPENDENCE,
expr.span,
"unsequenced read of a variable",
self.write_expr.span,
"whether read occurs before this write depends on evaluation order"
);
}
}
}
if_let_chain! {[
let QPath::Resolved(None, ref path) = *qpath,
path.segments.len() == 1,
let def::Def::Local(local_id) = self.cx.tables.qpath_def(qpath, expr.hir_id),
local_id == self.var,
// Check that this is a read, not a write.
!is_in_assignment_position(self.cx, expr),
], {
span_note_and_lint(
self.cx,
EVAL_ORDER_DEPENDENCE,
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
// 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::symbol::InternedString;
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
/// argument")` and `format!("{}", foo)` where `foo` is a string.
@ -47,7 +47,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if_let_chain!{[
let ExprPath(ref qpath) = fun.node,
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
check_static_str(cx, &args[0]),
// 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,
args.len() == 2,
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]));

View File

@ -2,6 +2,7 @@ use rustc::hir::intravisit;
use rustc::hir;
use rustc::lint::*;
use rustc::ty;
use rustc::hir::def::Def;
use std::collections::HashSet;
use syntax::ast;
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> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) {
Some(def_id)
fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<ast::NodeId> {
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &ty.node) {
Some(id)
} else {
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> {
cx: &'a LateContext<'a, 'tcx>,
ptrs: HashSet<hir::def_id::DefId>,
ptrs: HashSet<ast::NodeId>,
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> {
fn check_arg(&self, ptr: &hir::Expr) {
if let hir::ExprPath(ref qpath) = ptr.node {
let def = self.cx.tables.qpath_def(qpath, ptr.hir_id);
if self.ptrs.contains(&def.def_id()) {
span_lint(
self.cx,
NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span,
"this public function dereferences a raw pointer but is not marked `unsafe`",
);
if let Def::Local(id) = self.cx.tables.qpath_def(qpath, ptr.hir_id) {
if self.ptrs.contains(&id) {
span_lint(
self.cx,
NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span,
"this public function dereferences a raw pointer but is not marked `unsafe`",
);
}
}
}
}

View File

@ -1,6 +1,8 @@
use rustc::lint::*;
use rustc::hir;
use rustc::hir::BindingAnnotation;
use rustc::hir::def::Def;
use syntax::ast;
use utils::{snippet, span_lint_and_then};
/// **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 hir::StmtDecl(ref decl, _) = stmt.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::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 Some(value) = check_assign(cx, def_id, &*then),
!used_in_expr(cx, def_id, value),
let Some(value) = check_assign(cx, canonical_id, &*then),
!used_in_expr(cx, canonical_id, value),
], {
let span = stmt.span.to(if_.span);
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
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 if let Some(ref default) = decl.init {
(true, &**default)
@ -130,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
struct UsedVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
id: hir::def_id::DefId,
id: ast::NodeId,
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) {
if_let_chain! {[
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;
return;
@ -152,7 +155,7 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
fn check_assign<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
decl: hir::def_id::DefId,
decl: ast::NodeId,
block: &'tcx hir::Block,
) -> Option<&'tcx hir::Expr> {
if_let_chain! {[
@ -161,7 +164,8 @@ fn check_assign<'a, 'tcx>(
let hir::StmtSemi(ref expr, _) = expr.node,
let hir::ExprAssign(ref var, ref value) = expr.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 {
cx: cx,
@ -183,7 +187,7 @@ fn check_assign<'a, 'tcx>(
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 {
cx: cx,
id: id,

View File

@ -2,7 +2,6 @@ use itertools::Itertools;
use reexport::*;
use rustc::hir::*;
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::map::Node::{NodeBlock, NodeExpr, NodeStmt};
use rustc::lint::*;
@ -594,13 +593,14 @@ fn check_for_loop<'a, 'tcx>(
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! {[
let ExprPath(ref qpath) = expr.node,
let QPath::Resolved(None, ref path) = *qpath,
path.segments.len() == 1,
let Def::Local(local_id) = cx.tables.qpath_def(qpath, expr.hir_id),
// our variable!
cx.tables.qpath_def(qpath, expr.hir_id).def_id() == var
local_id == var
], {
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)
}
fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr, var: DefId) -> Option<FixedOffsetVar> {
fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr, var: DefId) -> Option<String> {
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: ast::NodeId) -> Option<String> {
match e.node {
ExprLit(ref l) => match l.node {
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>(
cx: &LateContext<'a, 'tcx>,
body: &Expr,
var: DefId,
var: ast::NodeId,
) -> Vec<(FixedOffsetVar, FixedOffsetVar)> {
fn get_assignment<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
e: &Expr,
var: DefId,
var: ast::NodeId,
) -> Option<(FixedOffsetVar, FixedOffsetVar)> {
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)) {
@ -759,7 +759,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
}) = higher::range(arg)
{
// 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 {
match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) {
("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
// 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
.into_iter()
@ -852,10 +852,10 @@ fn check_for_loop_range<'a, 'tcx>(
}) = higher::range(arg)
{
// 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 {
cx: cx,
var: def_id,
var: canonical_id,
indexed: HashMap::new(),
referenced: HashSet::new(),
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>,
def_id: DefId,
local: ast::NodeId,
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) {
if same_var(self.cx, expr, self.def_id) {
if same_var(self.cx, expr, self.local) {
self.used = true;
} else {
walk_expr(self, expr);
@ -1322,7 +1322,7 @@ struct VarVisitor<'a, 'tcx: 'a> {
/// context reference
cx: &'a LateContext<'a, 'tcx>,
/// var name to look for as index
var: DefId,
var: ast::NodeId,
/// indexed variables, the extend is `None` for global
indexed: HashMap<Name, Option<region::Scope>>,
/// 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,
], {
let index_used = same_var(self.cx, idx, self.var) || {
let mut used_visitor = DefIdUsedVisitor {
let mut used_visitor = LocalUsedVisitor {
cx: self.cx,
def_id: self.var,
local: self.var,
used: false,
};
walk_expr(&mut used_visitor, idx);
@ -1356,9 +1356,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if index_used {
let def = self.cx.tables.qpath_def(seqpath, seqexpr.hir_id);
match def {
Def::Local(..) | Def::Upvar(..) => {
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");
Def::Local(node_id) | Def::Upvar(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);
@ -1381,8 +1379,9 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
let ExprPath(ref qpath) = expr.node,
let QPath::Resolved(None, ref path) = *qpath,
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
self.nonindex = true;
} else {
@ -1672,11 +1671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
if let ExprPath(ref qpath) = expr.node {
let path_res = cx.tables.qpath_def(qpath, expr.hir_id);
if let Def::Local(def_id) = path_res {
let node_id = cx.tcx
.hir
.as_local_node_id(def_id)
.expect("That DefId should be valid");
if let Def::Local(node_id) = path_res {
return Some(node_id);
}
}

View File

@ -1,6 +1,6 @@
use rustc::lint::*;
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
/// `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) {
if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tables.qpath_def(qpath, path_expr.hir_id).def_id();
if match_def_path(cx.tcx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tables.expr_ty(&args[0]);
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) {
let forgot_ty = cx.tables.expr_ty(&args[0]);
if match forgot_ty.ty_adt_def() {
Some(def) => def.has_dtor(cx.tcx),
_ => false,
} {
span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type");
if match forgot_ty.ty_adt_def() {
Some(def) => def.has_dtor(cx.tcx),
_ => false,
} {
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::hir::*;
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
/// 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)> {
if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(ref qpath) = path.node {
let def_id = cx.tables.qpath_def(qpath, path.hir_id).def_id();
if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) {
fetch_const(cx, args, MinMax::Min)
} else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) {
fetch_const(cx, args, MinMax::Max)
} else {
None
}
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) {
fetch_const(cx, args, MinMax::Min)
} else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) {
fetch_const(cx, args, MinMax::Max)
} else {
None
}
})
} else {
None
}

View File

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

View File

@ -1,6 +1,5 @@
use rustc::hir::*;
use rustc::hir::intravisit::FnKind;
use rustc::hir::def_id::DefId;
use rustc::lint::*;
use rustc::ty::{self, TypeFoldable};
use rustc::traits;
@ -129,8 +128,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
!implements_trait(cx, ty, asref_trait, &[]),
!implements_borrow_trait,
let PatKind::Binding(mode, defid, ..) = arg.pat.node,
!moved_vars.contains(&defid),
let PatKind::Binding(mode, canonical_id, ..) = arg.pat.node,
!moved_vars.contains(&canonical_id),
], {
// Note: `toplevel_ref_arg` warns if `BindByRef`
if mode == BindingAnnotation::Mutable || mode == BindingAnnotation::RefMut {
@ -139,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
// Suggestion logic
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! {[
match_type(cx, ty, &paths::VEC),
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> {
cx: &'a LateContext<'a, 'tcx>,
moved_vars: HashSet<DefId>,
moved_vars: HashSet<NodeId>,
/// Spans which need to be prefixed with `*` for dereferencing the
/// suggested additional
/// reference.
spans_need_deref: HashMap<DefId, HashSet<Span>>,
spans_need_deref: HashMap<NodeId, HashSet<Span>>,
}
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>) {
let cmt = unwrap_downcast_or_interior(cmt);
if_let_chain! {[
let mc::Categorization::Local(vid) = cmt.cat,
let Some(def_id) = self.cx.tcx.hir.opt_local_def_id(vid),
], {
self.moved_vars.insert(def_id);
}}
if let mc::Categorization::Local(vid) = cmt.cat {
self.moved_vars.insert(vid);
}
}
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! {[
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;
loop {
@ -235,7 +230,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
// `match` and `if let`
if let ExprMatch(ref c, ..) = e.node {
self.spans_need_deref
.entry(def_id)
.entry(vid)
.or_insert_with(HashSet::new)
.insert(c.span);
}
@ -248,7 +243,7 @@ impl<'a, 'tcx> MovedVariablesCtxt<'a, 'tcx> {
let DeclLocal(ref local) = decl.node,
], {
self.spans_need_deref
.entry(def_id)
.entry(vid)
.or_insert_with(HashSet::new)
.insert(local.init
.as_ref()

View File

@ -1,7 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
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!`.
///
@ -40,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
let ExprCall(ref fun, ref params) = ex.node,
params.len() == 2,
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,
is_direct_expn_of(expr.span, "panic").is_some(),
let LitKind::Str(ref string, _) = lit.node,

View File

@ -1,7 +1,7 @@
use rustc::hir::*;
use rustc::hir::map::Node::{NodeImplItem, NodeItem};
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 format::get_argument_fmtstr_parts;
@ -72,9 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
if_let_chain! {[
let ExprCall(ref fun, ref args) = expr.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
// `print!` expansion.
@ -96,9 +95,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
args.len() == 1,
let ExprCall(ref args_fun, ref args_args) = args[0].node,
let ExprPath(ref qpath) = args_fun.node,
match_def_path(cx.tcx,
resolve_node(cx, qpath, args_fun.hir_id).def_id(),
&paths::FMT_ARGUMENTS_NEWV1),
let Some(const_def_id) = opt_def_id(resolve_node(cx, qpath, args_fun.hir_id)),
match_def_path(cx.tcx, const_def_id, &paths::FMT_ARGUMENTS_NEWV1),
args_args.len() == 2,
let ExprAddrOf(_, ref match_expr) = args_args[1].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)`
else if args.len() == 2 && match_def_path(cx.tcx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
if let ExprPath(ref qpath) = args[1].node {
let def_id = cx.tables.qpath_def(qpath, args[1].hir_id).def_id();
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() {
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
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) && is_expn_of(expr.span, "panic").is_none() {
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::codemap::{BytePos, Span};
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
/// (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 ExprPath(ref qpath) = fun.node,
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) ||
match_def_path(cx.tcx, def_id, &paths::REGEX_BUILDER_NEW) {
check_regex(cx, &args[0], true);

View File

@ -2,7 +2,7 @@ use rustc::lint::*;
use rustc::ty::{self, Ty};
use rustc::hir::*;
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
/// 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) {
if let ExprCall(ref path_expr, ref args) = e.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) {
let from_ty = cx.tables.expr_ty(&args[0]);
let to_ty = cx.tables.expr_ty(e);
if match_def_path(cx.tcx, def_id, &paths::TRANSMUTE) {
let from_ty = cx.tables.expr_ty(&args[0]);
let to_ty = cx.tables.expr_ty(e);
match (&from_ty.sty, &to_ty.sty) {
_ if from_ty == to_ty => span_lint(
cx,
USELESS_TRANSMUTE,
e.span,
&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
match (&from_ty.sty, &to_ty.sty) {
_ if from_ty == to_ty => span_lint(
cx,
USELESS_TRANSMUTE,
e.span,
&format!("transmute from a type (`{}`) to itself", from_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
(&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());
},
),
|db| {
let arg = sugg::Sugg::hir(cx, &args[0], "..");
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
("&mut *", "*mut")
} else {
("&*", "*const")
};
(&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::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 {
arg
} else {
arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, qpath, to_rty.ty)))
};
let arg = if from_pty.ty == to_rty.ty {
arg
} else {
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());
},
),
_ => return,
};
db.span_suggestion(e.span, "try", sugg::make_unop(deref, arg).to_string());
},
),
_ => return,
};
}
}
}
}

View File

@ -6,7 +6,7 @@
use rustc::hir;
use rustc::lint::LateContext;
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.
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::ExprPath(ref path) = fun.node,
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.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
return if match_def_path(cx.tcx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
// `vec![elem; size]` case
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
if_let_chain!{[
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 {
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);
if let Some(ref src) = source.dylib {
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::Const(id) |
Def::AssociatedConst(id) |
Def::Local(id) |
Def::Upvar(id, ..) |
Def::Macro(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..]),
let PatKind::Binding(_, defid, _, None) = pat[0].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;
}}