WIP compiles and doesn't crash (much) but tests are failing

This commit is contained in:
Oliver Schneider 2016-12-01 22:31:56 +01:00
parent f9fe50da1e
commit 59b0077565
47 changed files with 387 additions and 347 deletions

View File

@ -1,6 +1,9 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.104 — 2016-12-01
* Update to *rustc 1.15.0-nightly (1c448574b 2016-11-28)*
## 0.0.103 — 2016-11-25
* Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)*

View File

@ -105,7 +105,7 @@ impl LateLintPass for AttrPass {
}
match item.node {
ItemExternCrate(_) |
ItemUse(_) => {
ItemUse(_, _) => {
for attr in &item.attrs {
if let MetaItemKind::List(ref lint_list) = attr.value.node {
match &*attr.name().as_str() {
@ -113,7 +113,7 @@ impl LateLintPass for AttrPass {
// whitelist `unused_imports`
for lint in lint_list {
if is_word(lint, "unused_imports") {
if let ItemUse(_) = item.node {
if let ItemUse(_, _) = item.node {
return;
}
}
@ -193,8 +193,8 @@ fn is_relevant_expr(cx: &LateContext, expr: &Expr) -> bool {
ExprRet(Some(ref e)) => is_relevant_expr(cx, e),
ExprRet(None) | ExprBreak(_, None) => false,
ExprCall(ref path_expr, _) => {
if let ExprPath(..) = path_expr.node {
let fun_id = resolve_node(cx, path_expr.id).expect("function should be resolved").def_id();
if let ExprPath(ref qpath) = path_expr.node {
let fun_id = resolve_node(cx, qpath, path_expr.id).def_id();
!match_def_path(cx, fun_id, &paths::BEGIN_PANIC)
} else {
true

View File

@ -1,5 +1,5 @@
use rustc::hir::*;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc::lint::*;
use rustc_const_eval::lookup_const_by_id;
use syntax::ast::LitKind;
@ -245,18 +245,13 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
None
}
}
ExprPath(_, _) => {
{
// Important to let the borrow expire before the const lookup to avoid double
// borrowing.
let def_map = cx.tcx.def_map.borrow();
match def_map.get(&lit.id) {
Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id),
_ => None,
}
ExprPath(ref qpath) => {
let def = cx.tcx.tables().qpath_def(qpath, lit.id);
if let Def::Const(def_id) = def {
lookup_const_by_id(cx.tcx, def_id, None).and_then(|(l, _ty)| fetch_int_literal(cx, l))
} else {
None
}
.and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None))
.and_then(|(l, _ty)| fetch_int_literal(cx, l))
}
_ => None,
}

View File

@ -39,7 +39,7 @@ impl LintPass for BlackListedName {
impl LateLintPass for BlackListedName {
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatKind::Binding(_, ref ident, _) = pat.node {
if let PatKind::Binding(_, _, ref ident, _) = pat.node {
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
span_lint(cx,
BLACKLISTED_NAME,

View File

@ -1,7 +1,7 @@
#![allow(cast_possible_truncation)]
use rustc::lint::LateContext;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc_const_eval::lookup_const_by_id;
use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
use rustc::hir::*;
@ -10,7 +10,7 @@ use std::cmp::PartialOrd;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;
use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy};
use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy, NodeId};
use syntax::ptr::P;
#[derive(Debug, Copy, Clone)]
@ -252,7 +252,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
/// simple constant folding: Insert an expression, get a constant or none.
fn expr(&mut self, e: &Expr) -> Option<Constant> {
match e.node {
ExprPath(_, _) => self.fetch_path(e),
ExprPath(ref qpath) => self.fetch_path(qpath, e.id),
ExprBlock(ref block) => self.block(block),
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
ExprLit(ref lit) => Some(lit_to_constant(&lit.node)),
@ -285,21 +285,22 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}
/// lookup a possibly constant expression from a ExprPath
fn fetch_path(&mut self, e: &Expr) -> Option<Constant> {
fn fetch_path(&mut self, qpath: &QPath, id: NodeId) -> Option<Constant> {
if let Some(lcx) = self.lcx {
let mut maybe_id = None;
if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) {
maybe_id = Some(id);
}
// separate if lets to avoid double borrowing the def_map
if let Some(id) = maybe_id {
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) {
let ret = self.expr(const_expr);
if ret.is_some() {
self.needed_resolution = true;
let def = lcx.tcx.tables().qpath_def(qpath, id);
match def {
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let substs = Some(lcx.tcx.tables().node_id_item_substs(id)
.unwrap_or_else(|| lcx.tcx.intern_substs(&[])));
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, def_id, substs) {
let ret = self.expr(const_expr);
if ret.is_some() {
self.needed_resolution = true;
}
return ret;
}
return ret;
}
},
_ => {},
}
}
None

View File

@ -254,7 +254,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
bindings_impl(cx, pat, map);
}
}
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()) {
v.insert(cx.tcx.tables().pat_ty(pat));
}

View File

@ -5,7 +5,7 @@ use rustc::ty;
use rustc::hir::*;
use syntax::codemap::Span;
use utils::paths;
use utils::{is_automatically_derived, match_path, span_lint_and_then};
use utils::{is_automatically_derived, span_lint_and_then, match_path_old};
/// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
/// explicitly.
@ -89,7 +89,7 @@ impl LateLintPass for Derive {
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>,
hash_is_automatically_derived: bool) {
if_let_chain! {[
match_path(&trait_ref.path, &paths::HASH),
match_path_old(&trait_ref.path, &paths::HASH),
let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
], {
let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);
@ -131,7 +131,7 @@ fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_re
/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) {
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs);

View File

@ -38,8 +38,8 @@ impl LintPass for Pass {
impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(None, _) = path.node {
let def_id = cx.tcx.expect_def(path.id).def_id();
if let ExprPath(ref qpath) = path.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
if match_def_path(cx, def_id, &paths::DROP) {
if args.len() != 1 {
return;

View File

@ -2,8 +2,7 @@
use rustc::hir::*;
use rustc::hir::def::Def;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext};
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray};
use syntax::ast::NodeId;
use syntax::codemap::Span;
use utils::span_lint;
@ -48,24 +47,9 @@ impl EnumGlobUse {
if item.vis == Visibility::Public {
return; // re-exports are fine
}
if let ItemUse(ref item_use) = item.node {
if let ViewPath_::ViewPathGlob(_) = item_use.node {
if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) {
if let Some(node_id) = cx.tcx.map.as_local_node_id(def.full_def().def_id()) {
if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) {
if let ItemEnum(..) = it.node {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
} else {
let child = cx.sess().cstore.item_children(def.full_def().def_id());
if let Some(child) = child.first() {
if let Def::Variant(..) = child.def {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
}
}
if let ItemUse(ref path, UseKind::Glob) = item.node {
if let Def::Enum(_) = path.def {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
}

View File

@ -72,9 +72,9 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
_ => (),
}
for (a1, a2) in decl.inputs.iter().zip(args) {
if let PatKind::Binding(_, ident, _) = a1.pat.node {
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 let ExprPath(QPath::Resolved(None, ref p)) = a2.node {
if p.segments.len() != 1 {
// If it's a proper path, it can't be a local variable
return;

View File

@ -61,16 +61,18 @@ impl LateLintPass for EvalOrderDependence {
// Find a write to a local variable.
match expr.node {
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
if let ExprPath(None, ref path) = lhs.node {
if path.segments.len() == 1 {
let var = cx.tcx.expect_def(lhs.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 ExprPath(ref qpath) = lhs.node {
if let QPath::Resolved(_, ref path) = *qpath {
if path.segments.len() == 1 {
let var = cx.tcx.tables().qpath_def(qpath, lhs.id).def_id();
let mut visitor = ReadVisitor {
cx: cx,
var: var,
write_expr: expr,
last_expr: expr,
};
check_for_unsequenced_reads(&mut visitor);
}
}
}
}
@ -293,19 +295,21 @@ impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {
}
match expr.node {
ExprPath(None, ref path) => {
if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.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"
);
ExprPath(ref qpath) => {
if let QPath::Resolved(None, ref path) = *qpath {
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.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"
);
}
}
}
}

View File

@ -45,10 +45,9 @@ impl LateLintPass for Pass {
// `format!("{}", foo)` expansion
ExprCall(ref fun, ref args) => {
if_let_chain!{[
let ExprPath(..) = fun.node,
let ExprPath(ref qpath) = fun.node,
args.len() == 2,
let Some(fun) = resolve_node(cx, fun.id),
match_def_path(cx, fun.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
match_def_path(cx, resolve_node(cx, qpath, fun.id).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
@ -129,9 +128,8 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
exprs.len() == 1,
let ExprCall(_, ref args) = exprs[0].node,
args.len() == 2,
let ExprPath(None, _) = args[1].node,
let Some(fun) = resolve_node(cx, args[1].id),
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD),
let ExprPath(ref qpath) = args[1].node,
match_def_path(cx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD),
], {
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));

View File

@ -138,9 +138,9 @@ impl Functions {
}
}
fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
cx.tcx.def_map.borrow().get(&arg.pat.id).map(|pr| pr.full_def().def_id())
fn raw_ptr_arg(_cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
Some(def_id)
} else {
None
}
@ -183,8 +183,9 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
fn check_arg(&self, ptr: &hir::Expr) {
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) {
if self.ptrs.contains(&def.full_def().def_id()) {
if let hir::ExprPath(ref qpath) = ptr.node {
let def = self.cx.tcx.tables().qpath_def(qpath, ptr.id);
if self.ptrs.contains(&def.def_id()) {
span_lint(self.cx,
NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span,

View File

@ -63,7 +63,7 @@ impl LateLintPass for Pass {
}
}
PatKind::Path(_, ref path) if match_path(path, &paths::OPTION_NONE) => {
PatKind::Path(ref path) if match_path(path, &paths::OPTION_NONE) => {
"is_none()"
}

View File

@ -65,19 +65,18 @@ impl LateLintPass 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, ref name, None) = decl.pat.node,
let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id),
let hir::PatKind::Binding(mode, def_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.full_def().def_id(), cond),
let Some(value) = check_assign(cx, def.full_def().def_id(), then),
!used_in_expr(cx, def.full_def().def_id(), value),
!used_in_expr(cx, def_id, cond),
let Some(value) = check_assign(cx, def_id, then),
!used_in_expr(cx, def_id, value),
], {
let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);
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.full_def().def_id(), else_) {
if let Some(default) = check_assign(cx, def_id, else_) {
(else_.stmts.len() > 1, default)
} else if let Some(ref default) = decl.init {
(true, &**default)
@ -137,9 +136,8 @@ struct UsedVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'v hir::Expr) {
if_let_chain! {[
let hir::ExprPath(None, _) = expr.node,
let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id),
self.id == def.full_def().def_id(),
let hir::ExprPath(ref qpath) = expr.node,
self.id == self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id(),
], {
self.used = true;
return;
@ -154,9 +152,8 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::
let Some(expr) = block.stmts.iter().last(),
let hir::StmtSemi(ref expr, _) = expr.node,
let hir::ExprAssign(ref var, ref value) = expr.node,
let hir::ExprPath(None, _) = var.node,
let Some(def) = cx.tcx.def_map.borrow().get(&var.id),
decl == def.full_def().def_id(),
let hir::ExprPath(ref qpath) = var.node,
decl == cx.tcx.tables().qpath_def(qpath, var.id).def_id(),
], {
let mut v = UsedVisitor {
cx: cx,

View File

@ -256,7 +256,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents));
reg.register_late_lint_pass(box neg_multiply::NegMultiply);
reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
reg.register_late_lint_pass(box mem_forget::MemForget);
reg.register_late_lint_pass(box arithmetic::Arithmetic::default());
reg.register_late_lint_pass(box assign_ops::AssignOps);

View File

@ -239,12 +239,12 @@ impl<'v, 't> RefVisitor<'v, 't> {
self.lts
}
fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) {
let last_path_segment = path.segments.last().map(|s| &s.parameters);
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
if params.lifetimes.is_empty() {
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) {
match def {
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
if let QPath::Resolved(_, ref path) = *qpath {
let last_path_segment = path.segments.last().map(|s| &s.parameters);
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
if params.lifetimes.is_empty() {
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
Def::TyAlias(def_id) |
Def::Struct(def_id) => {
let generics = self.cx.tcx.item_generics(def_id);
@ -277,7 +277,7 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> {
TyRptr(None, _) => {
self.record(&None);
}
TyPath(_, ref path) => {
TyPath(ref path) => {
self.collect_anonymous_lifetimes(path, ty);
}
_ => (),

View File

@ -366,26 +366,28 @@ impl LateLintPass for Pass {
}
if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node {
let pat = &arms[0].pats[0].node;
if let (&PatKind::TupleStruct(ref path, ref pat_args, _),
if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _),
&ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) {
let iter_expr = &method_args[0];
if let Some(lhs_constructor) = path.segments.last() {
if &*method_name.node.as_str() == "next" &&
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
&*lhs_constructor.name.as_str() == "Some" &&
!is_refutable(cx, &pat_args[0]) &&
!is_iterator_used_after_while_let(cx, iter_expr) {
let iterator = snippet(cx, method_args[0].span, "_");
let loop_var = snippet(cx, pat_args[0].span, "_");
span_lint_and_then(cx,
WHILE_LET_ON_ITERATOR,
expr.span,
"this loop could be written as a `for` loop",
|db| {
db.span_suggestion(expr.span,
"try",
format!("for {} in {} {{ .. }}", loop_var, iterator));
});
if let QPath::Resolved(_, ref path) = *qpath {
if let Some(lhs_constructor) = path.segments.last() {
if &*method_name.node.as_str() == "next" &&
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
&*lhs_constructor.name.as_str() == "Some" &&
!is_refutable(cx, &pat_args[0]) &&
!is_iterator_used_after_while_let(cx, iter_expr) {
let iterator = snippet(cx, method_args[0].span, "_");
let loop_var = snippet(cx, pat_args[0].span, "_");
span_lint_and_then(cx,
WHILE_LET_ON_ITERATOR,
expr.span,
"this loop could be written as a `for` loop",
|db| {
db.span_suggestion(expr.span,
"try",
format!("for {} in {} {{ .. }}", loop_var, iterator));
});
}
}
}
}
@ -421,10 +423,10 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E
fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) {
// the var must be a single name
if let PatKind::Binding(_, ref ident, _) = pat.node {
if let PatKind::Binding(_, def_id, ref ident, _) = pat.node {
let mut visitor = VarVisitor {
cx: cx,
var: cx.tcx.expect_def(pat.id).def_id(),
var: def_id,
indexed: HashMap::new(),
nonindex: false,
};
@ -510,7 +512,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool {
let ExprMethodCall(method, _, ref len_args) = expr.node,
len_args.len() == 1,
&*method.node.as_str() == "len",
let ExprPath(_, ref path) = len_args[0].node,
let ExprPath(QPath::Resolved(_, ref path)) = len_args[0].node,
path.segments.len() == 1,
&path.segments[0].name == var
], {
@ -732,7 +734,7 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
match *pat {
PatKind::Wild => true,
PatKind::Binding(_, ident, None) if ident.node.as_str().starts_with('_') => {
PatKind::Binding(_, _, ident, None) if ident.node.as_str().starts_with('_') => {
let mut visitor = UsedVisitor {
var: ident.node,
used: false,
@ -751,7 +753,7 @@ struct UsedVisitor {
impl<'a> Visitor<'a> for UsedVisitor {
fn visit_expr(&mut self, expr: &Expr) {
if let ExprPath(None, ref path) = expr.node {
if let ExprPath(QPath::Resolved(None, ref path)) = expr.node {
if path.segments.len() == 1 && path.segments[0].name == self.var {
self.used = true;
return;
@ -771,20 +773,21 @@ struct VarVisitor<'v, 't: 'v> {
impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
fn visit_expr(&mut self, expr: &'v Expr) {
if let ExprPath(None, ref path) = expr.node {
if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var {
// we are referencing our variable! now check if it's as an index
if_let_chain! {[
let Some(parexpr) = get_parent_expr(self.cx, expr),
let ExprIndex(ref seqexpr, _) = parexpr.node,
let ExprPath(None, ref seqvar) = seqexpr.node,
seqvar.segments.len() == 1
], {
let def_map = self.cx.tcx.def_map.borrow();
if let Some(def) = def_map.get(&seqexpr.id) {
match def.base_def {
if let ExprPath(ref qpath) = expr.node {
if let QPath::Resolved(None, ref path) = *qpath {
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
// we are referencing our variable! now check if it's as an index
if_let_chain! {[
let Some(parexpr) = get_parent_expr(self.cx, expr),
let ExprIndex(ref seqexpr, _) = parexpr.node,
let ExprPath(ref seqpath) = seqexpr.node,
let QPath::Resolved(None, ref seqvar) = *seqpath,
seqvar.segments.len() == 1
], {
let def = self.cx.tcx.tables().qpath_def(seqpath, seqexpr.id);
match def {
Def::Local(..) | Def::Upvar(..) => {
let def_id = def.base_def.def_id();
let def_id = def.def_id();
let node_id = self.cx.tcx.map.as_local_node_id(def_id).unwrap();
let extent = self.cx.tcx.region_maps.var_scope(node_id);
@ -797,11 +800,11 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
}
_ => (),
}
}
}}
// we are not indexing anything, record that
self.nonindex = true;
return;
}}
// we are not indexing anything, record that
self.nonindex = true;
return;
}
}
}
walk_expr(self, expr);
@ -1002,7 +1005,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
// Look for declarations of the variable
if let DeclLocal(ref local) = decl.node {
if local.pat.id == self.var_id {
if let PatKind::Binding(_, ref ident, _) = local.pat.node {
if let PatKind::Binding(_, _, ref ident, _) = local.pat.node {
self.name = Some(ident.node);
self.state = if let Some(ref init) = local.init {
@ -1071,8 +1074,9 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
}
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
if let Some(path_res) = cx.tcx.def_map.borrow().get(&expr.id) {
if let Def::Local(def_id) = path_res.base_def {
if let ExprPath(ref qpath) = expr.node {
let path_res = cx.tcx.tables().qpath_def(qpath, expr.id);
if let Def::Local(def_id) = path_res {
let node_id = cx.tcx.map.as_local_node_id(def_id).expect("That DefId should be valid");
return Some(node_id);
}

View File

@ -64,7 +64,7 @@ impl LateLintPass for Pass {
}
}}
}
ExprPath(_, ref path) => {
ExprPath(ref path) => {
if match_path(path, &paths::CLONE) {
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
span_help_and_lint(cx,
@ -85,7 +85,7 @@ impl LateLintPass for Pass {
fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
match expr.node {
ExprPath(None, ref path) => {
ExprPath(QPath::Resolved(None, ref path)) => {
let arg_segment = [PathSegment {
name: id,
parameters: PathParameters::none(),
@ -108,7 +108,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s
fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
match pat.node {
PatKind::Binding(_, name, None) => Some(name.node),
PatKind::Binding(_, _, name, None) => Some(name.node),
PatKind::Ref(ref subpat, _) => get_arg_name(subpat),
_ => None,
}

View File

@ -210,8 +210,8 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
}
path.to_string()
}
PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(),
PatKind::Path(None, ref path) => path.to_string(),
PatKind::Binding(BindByValue(MutImmutable), _, ident, None) => ident.node.to_string(),
PatKind::Path(ref path) => path.to_string(),
_ => return,
};

View File

@ -30,8 +30,8 @@ impl LintPass for MemForget {
impl LateLintPass for MemForget {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(None, _) = path_expr.node {
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);

View File

@ -701,7 +701,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
}
if name == "unwrap_or" {
if let hir::ExprPath(_, ref path) = fun.node {
if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = fun.node {
let path: &str = &path.segments
.last()
.expect("A path must have at least one segment")
@ -877,7 +877,7 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
if_let_chain!{[
let hir::ExprCall(ref fun, ref args) = new.node,
args.len() == 1,
let hir::ExprPath(None, ref path) = fun.node,
let hir::ExprPath(ref path) = fun.node,
match_path(path, &paths::CSTRING_NEW),
], {
span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span,
@ -1188,7 +1188,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
let Some(args) = method_chain_args(chain, &["chars", "next"]),
let hir::ExprCall(ref fun, ref arg_char) = other.node,
arg_char.len() == 1,
let hir::ExprPath(None, ref path) = fun.node,
let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = fun.node,
path.segments.len() == 1 && &*path.segments[0].name.as_str() == "Some"
], {
let self_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty_adjusted(&args[0][0]));
@ -1408,7 +1408,7 @@ impl OutType {
}
fn is_bool(ty: &hir::Ty) -> bool {
if let hir::TyPath(None, ref p) = ty.node {
if let hir::TyPath(ref p) = ty.node {
match_path(p, &["bool"])
} else {
false

View File

@ -61,8 +61,8 @@ 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(None, _) = path.node {
let def_id = cx.tcx.expect_def(path.id).def_id();
if let ExprPath(ref qpath) = path.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
if match_def_path(cx, def_id, &paths::CMP_MIN) {
fetch_const(args, MinMax::Min)

View File

@ -173,7 +173,7 @@ impl LateLintPass for Pass {
return;
}
for arg in &decl.inputs {
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node {
span_lint(cx,
TOPLEVEL_REF_ARG,
arg.pat.span,
@ -186,7 +186,7 @@ impl LateLintPass for Pass {
if_let_chain! {[
let StmtDecl(ref d, _) = s.node,
let DeclLocal(ref l) = d.node,
let PatKind::Binding(BindByRef(mt), i, None) = l.pat.node,
let PatKind::Binding(BindByRef(mt), _, i, None) = l.pat.node,
let Some(ref init) = l.init
], {
let init = Sugg::hir(cx, init, "..");
@ -220,10 +220,10 @@ impl LateLintPass for Pass {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
let op = cmp.node;
if op.is_comparison() {
if let ExprPath(_, ref path) = left.node {
if let ExprPath(QPath::Resolved(_, ref path)) = left.node {
check_nan(cx, path, expr.span);
}
if let ExprPath(_, ref path) = right.node {
if let ExprPath(QPath::Resolved(_, ref path)) = right.node {
check_nan(cx, path, expr.span);
}
check_to_owned(cx, left, right, true, cmp.span);
@ -262,19 +262,23 @@ impl LateLintPass for Pass {
return;
}
let binding = match expr.node {
ExprPath(_, ref path) => {
let binding = path.segments
.last()
.expect("path should always have at least one segment")
.name
.as_str();
if binding.starts_with('_') &&
!binding.starts_with("__") &&
&*binding != "_result" && // FIXME: #944
is_used(cx, expr) &&
// don't lint if the declaration is in a macro
non_macro_local(cx, &cx.tcx.expect_def(expr.id)) {
Some(binding)
ExprPath(ref qpath) => {
if let QPath::Resolved(_, ref path) = *qpath {
let binding = path.segments
.last()
.expect("path should always have at least one segment")
.name
.as_str();
if binding.starts_with('_') &&
!binding.starts_with("__") &&
&*binding != "_result" && // FIXME: #944
is_used(cx, expr) &&
// don't lint if the declaration is in a macro
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
Some(binding)
} else {
None
}
} else {
None
}
@ -299,7 +303,7 @@ impl LateLintPass for Pass {
}
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatKind::Binding(_, ref ident, Some(ref right)) = pat.node {
if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node {
if right.node == PatKind::Wild {
span_lint(cx,
REDUNDANT_PATTERN,
@ -366,7 +370,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
}
}
ExprCall(ref path, ref v) if v.len() == 1 => {
if let ExprPath(None, ref path) = path.node {
if let ExprPath(ref path) = path.node {
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) {
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
} else {

View File

@ -42,7 +42,7 @@ impl LateLintPass for UnnecessaryMutPassed {
.expect("A function with an unknown type is called. \
If this happened, the compiler would have \
aborted the compilation long ago");
if let ExprPath(_, ref path) = fn_expr.node {
if let ExprPath(ref path) = fn_expr.node {
check_arguments(cx, arguments, function_type, &path.to_string());
}
}

View File

@ -57,7 +57,7 @@ impl LateLintPass for NeedlessBorrow {
if in_macro(cx, pat.span) {
return;
}
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node {
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _, _) = pat.node {
if let ty::TyRef(_, ref tam) = cx.tcx.tables().pat_ty(pat).sty {
if tam.mutbl == MutImmutable {
if let ty::TyRef(..) = tam.ty.sty {

View File

@ -1,5 +1,5 @@
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource};
use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then};
use std::ops::Deref;
@ -68,13 +68,17 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
}
}
Expr_::ExprCall(ref callee, ref args) => {
let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
match def {
Some(Def::Struct(..)) |
Some(Def::Variant(..)) |
Some(Def::StructCtor(..)) |
Some(Def::VariantCtor(..)) => args.iter().all(|arg| has_no_effect(cx, arg)),
_ => false,
if let Expr_::ExprPath(ref qpath) = callee.node {
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
match def {
Def::Struct(..) |
Def::Variant(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => args.iter().all(|arg| has_no_effect(cx, arg)),
_ => false,
}
} else {
false
}
}
Expr_::ExprBlock(ref block) => {
@ -146,12 +150,17 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
}
Expr_::ExprCall(ref callee, ref args) => {
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
Some(Def::Struct(..)) |
Some(Def::Variant(..)) |
Some(Def::StructCtor(..)) |
Some(Def::VariantCtor(..)) => Some(args.iter().collect()),
_ => None,
if let Expr_::ExprPath(ref qpath) = callee.node {
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
match def {
Def::Struct(..) |
Def::Variant(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => Some(args.iter().collect()),
_ => None,
}
} else {
None
}
}
Expr_::ExprBlock(ref block) => {

View File

@ -46,7 +46,7 @@ impl LateLintPass for Pass {
let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result<T,E>.ok()
let PatKind::TupleStruct(ref x, ref y, _) = body[0].pats[0].node, //get operation
let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node, //get operation
method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;
], {

View File

@ -35,9 +35,9 @@ impl LateLintPass for OverflowCheckConditional {
if_let_chain! {[
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = second.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()
@ -57,9 +57,9 @@ impl LateLintPass for OverflowCheckConditional {
if_let_chain! {[
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node,
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = first.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()

View File

@ -39,9 +39,8 @@ impl LateLintPass for Pass {
let Some(ref ex) = block.expr,
let ExprCall(ref fun, ref params) = ex.node,
params.len() == 2,
let ExprPath(None, _) = fun.node,
let Some(fun) = resolve_node(cx, fun.id),
match_def_path(cx, fun.def_id(), &paths::BEGIN_PANIC),
let ExprPath(ref qpath) = fun.node,
match_def_path(cx, resolve_node(cx, qpath, fun.id).def_id(), &paths::BEGIN_PANIC),
let ExprLit(ref lit) = params[0].node,
is_direct_expn_of(cx, params[0].span, "panic").is_some(),
let LitKind::Str(ref string, _) = lit.node,

View File

@ -40,7 +40,7 @@ impl LateLintPass for Pass {
if_let_chain! {[
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
!is_automatically_derived(&*item.attrs),
cx.tcx.expect_def(trait_ref.ref_id).def_id() == cx.tcx.lang_items.eq_trait().unwrap(),
trait_ref.path.def.def_id() == cx.tcx.lang_items.eq_trait().unwrap(),
], {
for impl_item in impl_items {
if &*impl_item.name.as_str() == "ne" {

View File

@ -2,7 +2,7 @@ use rustc::hir::*;
use rustc::hir::map::Node::{NodeItem, NodeImplItem};
use rustc::lint::*;
use utils::paths;
use utils::{is_expn_of, match_path, match_def_path, resolve_node, span_lint};
use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path_old};
use format::get_argument_fmtstr_parts;
/// **What it does:** This lint warns when you using `print!()` with a format string that
@ -69,9 +69,9 @@ impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if_let_chain! {[
let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(..) = fun.node,
let Some(fun) = resolve_node(cx, fun.id),
let ExprPath(ref qpath) = fun.node,
], {
let fun = resolve_node(cx, qpath, fun.id);
let fun_id = fun.def_id();
// Search for `std::io::_print(..)` which is unique in a
@ -93,9 +93,8 @@ impl LateLintPass for Pass {
// ensure we're calling Arguments::new_v1
args.len() == 1,
let ExprCall(ref args_fun, ref args_args) = args[0].node,
let ExprPath(..) = args_fun.node,
let Some(def) = resolve_node(cx, args_fun.id),
match_def_path(cx, def.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
let ExprPath(ref qpath) = args_fun.node,
match_def_path(cx, resolve_node(cx, qpath, args_fun.id).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,
@ -121,8 +120,8 @@ impl LateLintPass for Pass {
// Search for something like
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
else if args.len() == 2 && match_def_path(cx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
if let ExprPath(None, _) = args[1].node {
let def_id = resolve_node(cx, args[1].id).unwrap().def_id();
if let ExprPath(ref qpath) = args[1].node {
let def_id = cx.tcx.tables().qpath_def(qpath, args[1].id).def_id();
if match_def_path(cx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) &&
is_expn_of(cx, expr.span, "panic").is_none() {
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
@ -141,7 +140,7 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
// `Debug` impl
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
return match_path(&tr.path, &["Debug"]);
return match_path_old(&tr.path, &["Debug"]);
}
}
}

View File

@ -77,7 +77,7 @@ impl LateLintPass for PointerPass {
check_fn(cx, &sig.decl, item.id);
}
}
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if let ExprBinary(ref op, ref l, ref r) = expr.node {
if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) {
@ -116,7 +116,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
fn is_null_path(expr: &Expr) -> bool {
if let ExprCall(ref pathexp, ref args) = expr.node {
if args.is_empty() {
if let ExprPath(_, ref path) = pathexp.node {
if let ExprPath(ref path) = pathexp.node {
return match_path(path, &paths::PTR_NULL) || match_path(path, &paths::PTR_NULL_MUT)
}
}

View File

@ -73,15 +73,19 @@ impl LateLintPass for StepByZero {
let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node,
&*len_name.as_str() == "len" && len_args.len() == 1,
// .iter() and .len() called on same Path
let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node,
let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node,
let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node,
let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node,
iter_path == len_path
], {
span_lint(cx,
RANGE_ZIP_WITH_LEN,
expr.span,
&format!("It is more idiomatic to use {}.iter().enumerate()",
snippet(cx, iter_args[0].span, "_")));
let Path { segments: ref iter_path, .. } = **iter_path;
let Path { segments: ref len_path, .. } = **len_path;
if iter_path == len_path {
span_lint(cx,
RANGE_ZIP_WITH_LEN,
expr.span,
&format!("It is more idiomatic to use {}.iter().enumerate()",
snippet(cx, iter_args[0].span, "_")));
}
}}
}
}

View File

@ -115,10 +115,10 @@ impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
if_let_chain!{[
let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(ref qpath) = fun.node,
args.len() == 1,
let Some(def) = cx.tcx.def_map.borrow().get(&fun.id),
], {
let def_id = def.full_def().def_id();
let def_id = cx.tcx.tables().qpath_def(qpath, fun.id).def_id();
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
check_regex(cx, &args[0], true);

View File

@ -29,7 +29,7 @@ impl LintPass for Serde {
impl LateLintPass for Serde {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node {
let did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
let did = trait_ref.path.def.def_id();
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
if did == visit_did {
let mut seen_str = None;

View File

@ -1,8 +1,8 @@
use reexport::*;
use rustc::lint::*;
use rustc::hir::def::Def;
use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, FnKind};
use rustc::ty;
use std::ops::Deref;
use syntax::codemap::Span;
use utils::{higher, in_external_macro, snippet, span_lint_and_then};
@ -92,7 +92,7 @@ impl LateLintPass for Pass {
fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
let mut bindings = Vec::new();
for arg in &decl.inputs {
if let PatKind::Binding(_, ident, _) = arg.pat.node {
if let PatKind::Binding(_, _, ident, _) = arg.pat.node {
bindings.push((ident.node, ident.span))
}
}
@ -135,10 +135,10 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
}
}
fn is_binding(cx: &LateContext, pat: &Pat) -> bool {
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) |
Some(Def::Struct(..)) => false,
fn is_binding(cx: &LateContext, pat_id: NodeId) -> bool {
let var_ty = cx.tcx.tables().node_id_to_type(pat_id);
match var_ty.sty {
ty::TyAdt(..) => false,
_ => true,
}
}
@ -146,9 +146,9 @@ fn is_binding(cx: &LateContext, pat: &Pat) -> bool {
fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) {
// TODO: match more stuff / destructuring
match pat.node {
PatKind::Binding(_, ref ident, ref inner) => {
PatKind::Binding(_, _, ref ident, ref inner) => {
let name = ident.node;
if is_binding(cx, pat) {
if is_binding(cx, pat.id) {
let mut new_binding = true;
for tup in bindings.iter_mut() {
if tup.0 == name {
@ -344,7 +344,7 @@ fn is_self_shadow(name: Name, expr: &Expr) -> bool {
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
}
ExprUnary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
ExprPath(_, ref path) => path_eq_name(name, path),
ExprPath(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
_ => false,
}
}

View File

@ -65,7 +65,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
let StmtDecl(ref tmp, _) = w[0].node,
let DeclLocal(ref tmp) = tmp.node,
let Some(ref tmp_init) = tmp.init,
let PatKind::Binding(_, ref tmp_name, None) = tmp.pat.node,
let PatKind::Binding(_, _, ref tmp_name, None) = tmp.pat.node,
// foo() = bar();
let StmtSemi(ref first, _) = w[1].node,
@ -74,7 +74,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
// bar() = t;
let StmtSemi(ref second, _) = w[2].node,
let ExprAssign(ref lhs2, ref rhs2) = second.node,
let ExprPath(None, ref rhs2) = rhs2.node,
let ExprPath(QPath::Resolved(None, ref rhs2)) = rhs2.node,
rhs2.segments.len() == 1,
tmp_name.node.as_str() == rhs2.segments[0].name.as_str(),

View File

@ -87,8 +87,8 @@ impl LintPass for Transmute {
impl LateLintPass for Transmute {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(None, ref path) = path_expr.node {
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
let from_ty = cx.tcx.tables().expr_ty(&args[0]);
@ -173,7 +173,7 @@ impl LateLintPass for Transmute {
let arg = if from_pty.ty == to_rty.ty {
arg
} else {
arg.as_ty(&format!("{} {}", cast, get_type_snippet(cx, path, 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());
@ -190,8 +190,9 @@ impl LateLintPass for Transmute {
/// Get the snippet of `Bar` in `…::transmute<Foo, &Bar>`. If that snippet is not available , use
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
/// lifetime, but it should be rare.
fn get_type_snippet(cx: &LateContext, path: &Path, to_rty: ty::Ty) -> String {
fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: ty::Ty) -> String {
if_let_chain!{[
let QPath::Resolved(_, ref path) = *path,
let Some(seg) = path.segments.last(),
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
let Some(to_ty) = ang.types.get(1),

View File

@ -7,7 +7,7 @@ use std::cmp::Ordering;
use syntax::ast::{IntTy, UintTy, FloatTy};
use syntax::codemap::Span;
use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet,
span_help_and_lint, span_lint};
span_help_and_lint, span_lint, opt_def_id};
use utils::paths;
/// Handles all the linting of funky types
@ -74,17 +74,19 @@ impl LateLintPass for TypePass {
if in_macro(cx, ast_ty.span) {
return;
}
if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) {
if let def::Def::Struct(..) = did.full_def() {
if Some(did.full_def().def_id()) == cx.tcx.lang_items.owned_box() {
if let TyPath(ref qpath) = ast_ty.node {
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
if let Some(def_id) = opt_def_id(def) {
if def_id == cx.tcx.lang_items.owned_box().unwrap() {
if_let_chain! {[
let TyPath(_, ref path) = ast_ty.node,
let QPath::Resolved(_, ref path) = *qpath,
let Some(ref last) = path.segments.last(),
let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
let Some(ref vec) = ag.types.get(0),
let Some(did) = cx.tcx.def_map.borrow().get(&vec.id),
let def::Def::Struct(..) = did.full_def(),
match_def_path(cx, did.full_def().def_id(), &paths::VEC),
let TyPath(ref qpath) = vec.node,
let def::Def::Struct(..) = cx.tcx.tables().qpath_def(qpath, vec.id),
let Some(did) = opt_def_id(cx.tcx.tables().qpath_def(qpath, vec.id)),
match_def_path(cx, did, &paths::VEC),
], {
span_help_and_lint(cx,
BOX_VEC,
@ -92,12 +94,12 @@ impl LateLintPass for TypePass {
"you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`",
"`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation.");
}}
} else if match_def_path(cx, did.full_def().def_id(), &paths::LINKED_LIST) {
} else if match_def_path(cx, def_id, &paths::LINKED_LIST) {
span_help_and_lint(cx,
LINKEDLIST,
ast_ty.span,
"I see you're using a LinkedList! Perhaps you meant some other data structure?",
"a VecDeque might work");
LINKEDLIST,
ast_ty.span,
"I see you're using a LinkedList! Perhaps you meant some other data structure?",
"a VecDeque might work");
}
}
}

View File

@ -1,6 +1,5 @@
use rustc::hir::*;
use rustc::lint::*;
use syntax::ast::Name;
use syntax::ast::*;
use syntax::codemap::Span;
use syntax::symbol::InternedString;
use utils::span_lint;
@ -34,16 +33,16 @@ impl LintPass for UnsafeNameRemoval {
}
}
impl LateLintPass for UnsafeNameRemoval {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemUse(ref item_use) = item.node {
impl EarlyLintPass for UnsafeNameRemoval {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
if let ItemKind::Use(ref item_use) = item.node {
match item_use.node {
ViewPath_::ViewPathSimple(ref name, ref path) => {
unsafe_to_safe_check(
path.segments
.last()
.expect("use paths cannot be empty")
.name,
.identifier,
*name,
cx, &item.span
);
@ -62,9 +61,9 @@ impl LateLintPass for UnsafeNameRemoval {
}
}
fn unsafe_to_safe_check(old_name: Name, new_name: Name, cx: &LateContext, span: &Span) {
let old_str = old_name.as_str();
let new_str = new_name.as_str();
fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: &Span) {
let old_str = old_name.name.as_str();
let new_str = new_name.name.as_str();
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
span_lint(cx,
UNSAFE_REMOVED_FROM_NAME,

View File

@ -66,7 +66,7 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor {
match expr.node {
hir::ExprBreak(Some(label), _) |
hir::ExprAgain(Some(label)) => {
self.labels.remove(&label.node.as_str());
self.labels.remove(&label.name.as_str());
}
hir::ExprLoop(_, Some(label), _) |
hir::ExprWhile(_, _, Some(label)) => {

View File

@ -44,19 +44,6 @@ pub struct Range<'a> {
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
pub fn range(expr: &hir::Expr) -> Option<Range> {
/// Skip unstable blocks. To be removed when ranges get stable.
fn unwrap_unstable(expr: &hir::Expr) -> &hir::Expr {
if let hir::ExprBlock(ref block) = expr.node {
if block.rules == hir::BlockCheckMode::PushUnstableBlock || block.rules == hir::BlockCheckMode::PopUnstableBlock {
if let Some(ref expr) = block.expr {
return expr;
}
}
}
expr
}
/// Find the field named `name` in the field. Always return `Some` for convenience.
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
let expr = &fields.iter()
@ -64,14 +51,14 @@ pub fn range(expr: &hir::Expr) -> Option<Range> {
.unwrap_or_else(|| panic!("missing {} field for range", name))
.expr;
Some(unwrap_unstable(expr))
Some(expr)
}
// The range syntax is expanded to literal paths starting with `core` or `std` depending on
// `#[no_std]`. Testing both instead of resolving the paths.
match unwrap_unstable(expr).node {
hir::ExprPath(None, ref path) => {
match expr.node {
hir::ExprPath(ref path) => {
if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
Some(Range {
start: None,
@ -168,10 +155,10 @@ pub enum VecArgs<'a> {
pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> {
if_let_chain!{[
let hir::ExprCall(ref fun, ref args) = expr.node,
let hir::ExprPath(_, ref path) = fun.node,
let Some(fun_def) = resolve_node(cx, fun.id),
let hir::ExprPath(ref path) = fun.node,
is_expn_of(cx, fun.span, "vec").is_some(),
], {
let fun_def = resolve_node(cx, path, fun.id);
return if match_def_path(cx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
// `vec![elem; size]` case
Some(VecArgs::Repeat(&args[0], &args[1]))

View File

@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
match (&left.node, &right.node) {
(&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
(&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str()),
(&ExprAgain(li), &ExprAgain(ri)) => both(&li, &ri, |l, r| l.name.as_str() == r.name.as_str()),
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
(&ExprAssignOp(ref lo, ref ll, ref lr), &ExprAssignOp(ref ro, ref rl, ref rr)) => {
lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
@ -82,7 +82,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
})
}
(&ExprBreak(li, ref le), &ExprBreak(ri, ref re)) =>
both(&li, &ri, |l, r| l.node.as_str() == r.node.as_str())
both(&li, &ri, |l, r| l.name.as_str() == r.name.as_str())
&& both(le, re, |l, r| self.eq_expr(l, r)),
(&ExprBox(ref l), &ExprBox(ref r)) => self.eq_expr(l, r),
(&ExprCall(ref l_fun, ref l_args), &ExprCall(ref r_fun, ref r_args)) => {
@ -118,11 +118,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
(&ExprRepeat(ref le, ref ll), &ExprRepeat(ref re, ref rl)) => self.eq_expr(le, re) && self.eq_expr(ll, rl),
(&ExprRet(ref l), &ExprRet(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
(&ExprPath(ref l_qself, ref l_subpath), &ExprPath(ref r_qself, ref r_subpath)) => {
both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath)
}
(&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r),
(&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => {
self.eq_path(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) &&
self.eq_qpath(l_path, r_path) && both(lo, ro, |l, r| self.eq_expr(l, r)) &&
over(lf, rf, |l, r| self.eq_field(l, r))
}
(&ExprTup(ref l_tup), &ExprTup(ref r_tup)) => self.eq_exprs(l_tup, r_tup),
@ -153,14 +151,12 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
match (&left.node, &right.node) {
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
(&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => {
self.eq_path(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
}
(&PatKind::Binding(ref lb, ref li, ref lp), &PatKind::Binding(ref rb, ref ri, ref rp)) => {
lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
}
(&PatKind::Path(ref ql, ref l), &PatKind::Path(ref qr, ref r)) => {
both(ql, qr, |ql, qr| self.eq_qself(ql, qr)) && self.eq_path(l, r)
(&PatKind::Binding(ref lb, ref ld, ref li, ref lp), &PatKind::Binding(ref rb, ref rd, ref ri, ref rp)) => {
lb == rb && ld == rd && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
}
(&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r),
(&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
ls == rs && over(l, r, |l, r| self.eq_pat(l, r))
@ -178,6 +174,18 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
}
}
fn eq_qpath(&self, left: &QPath, right: &QPath) -> bool {
match (left, right) {
(&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => {
both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath)
},
(&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => {
self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
},
_ => false,
}
}
fn eq_path(&self, left: &Path, right: &Path) -> bool {
left.global == right.global &&
over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
@ -208,10 +216,6 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
self.eq_path_parameters(&left.parameters, &right.parameters)
}
fn eq_qself(&self, left: &QSelf, right: &QSelf) -> bool {
left.ty.node == right.ty.node && left.position == right.position
}
fn eq_ty(&self, left: &Ty, right: &Ty) -> bool {
match (&left.node, &right.node) {
(&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
@ -222,9 +226,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
(&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
}
(&TyPath(ref lq, ref l_path), &TyPath(ref rq, ref r_path)) => {
both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path)
}
(&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, r),
(&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)),
(&TyInfer, &TyInfer) => true,
_ => false,
@ -318,7 +320,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
let c: fn(_) -> _ = ExprAgain;
c.hash(&mut self.s);
if let Some(i) = i {
self.hash_name(&i.node);
self.hash_name(&i.name);
}
}
ExprAssign(ref l, ref r) => {
@ -350,7 +352,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
let c: fn(_, _) -> _ = ExprBreak;
c.hash(&mut self.s);
if let Some(i) = i {
self.hash_name(&i.node);
self.hash_name(&i.name);
}
if let Some(ref j) = *j {
self.hash_expr(&*j);
@ -452,16 +454,16 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
self.hash_expr(e);
}
}
ExprPath(ref _qself, ref subpath) => {
let c: fn(_, _) -> _ = ExprPath;
ExprPath(ref qpath) => {
let c: fn(_) -> _ = ExprPath;
c.hash(&mut self.s);
self.hash_path(subpath);
self.hash_qpath(qpath);
}
ExprStruct(ref path, ref fields, ref expr) => {
let c: fn(_, _, _) -> _ = ExprStruct;
c.hash(&mut self.s);
self.hash_path(path);
self.hash_qpath(path);
for f in fields {
self.hash_name(&f.name.node);
@ -526,6 +528,23 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
n.as_str().hash(&mut self.s);
}
pub fn hash_qpath(&mut self, p: &QPath) {
match *p {
QPath::Resolved(ref _ty, ref path) => {
let c: fn(_, _) -> _ = QPath::Resolved;
c.hash(&mut self.s);
// self.hash_ty(ty); FIXME
self.hash_path(path);
},
QPath::TypeRelative(ref _ty, ref seg) => {
let c: fn(_, _) -> _ = QPath::TypeRelative;
c.hash(&mut self.s);
// self.hash_ty(ty); FIXME
self.hash_name(&seg.name);
},
}
}
pub fn hash_path(&mut self, p: &Path) {
p.global.hash(&mut self.s);
for p in &p.segments {

View File

@ -275,11 +275,14 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
println!("{}index expr:", ind);
print_expr(cx, idx, indent + 1);
},
hir::ExprPath(ref sel, ref path) => {
println!("{}Path, {}", ind, ty);
println!("{}self: {:?}", ind, sel);
hir::ExprPath(hir::QPath::Resolved(ref ty, ref path)) => {
println!("{}Resolved Path, {:?}", ind, ty);
println!("{}path: {:?}", ind, path);
},
hir::ExprPath(hir::QPath::TypeRelative(ref ty, ref seg)) => {
println!("{}Relative Path, {:?}", ind, ty);
println!("{}seg: {:?}", ind, seg);
}
hir::ExprAddrOf(ref muta, ref e) => {
println!("{}AddrOf, {}", ind, ty);
println!("mutability: {:?}", muta);
@ -354,7 +357,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
println!("weird extern crate without a crate id");
}
}
hir::ItemUse(ref path) => println!("{:?}", path.node),
hir::ItemUse(ref path, ref kind) => println!("{:?}, {:?}", path, kind),
hir::ItemStatic(..) => println!("static item of type {:#?}", cx.tcx.item_type(did)),
hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.item_type(did)),
hir::ItemFn(..) => {
@ -383,13 +386,11 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
println!("trait has no default impl");
}
},
hir::ItemDefaultImpl(_, ref trait_ref) => {
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
println!("default impl for `{}`", cx.tcx.item_path_str(trait_did));
hir::ItemDefaultImpl(_, ref _trait_ref) => {
println!("default impl");
},
hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => {
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
println!("impl of trait `{}`", cx.tcx.item_path_str(trait_did));
hir::ItemImpl(_, _, _, Some(ref _trait_ref), _, _) => {
println!("trait impl");
},
hir::ItemImpl(_, _, _, None, _, _) => {
println!("impl");
@ -402,7 +403,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
println!("{}+", ind);
match pat.node {
hir::PatKind::Wild => println!("{}Wild", ind),
hir::PatKind::Binding(ref mode, ref name, ref inner) => {
hir::PatKind::Binding(ref mode, _, ref name, ref inner) => {
println!("{}Binding", ind);
println!("{}mode: {:?}", ind, mode);
println!("{}name: {}", ind, name.node);
@ -434,11 +435,14 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
print_pat(cx, field, indent + 1);
}
},
hir::PatKind::Path(ref sel, ref path) => {
println!("{}Path", ind);
println!("{}self: {:?}", ind, sel);
hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
println!("{}Resolved Path, {:?}", ind, ty);
println!("{}path: {:?}", ind, path);
},
hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
println!("{}Relative Path, {:?}", ind, ty);
println!("{}seg: {:?}", ind, seg);
},
hir::PatKind::Tuple(ref pats, opt_dots_position) => {
println!("{}Tuple", ind);
if let Some(dot_position) = opt_dots_position {

View File

@ -140,7 +140,7 @@ impl LateLintPass for LintWithoutLintPass {
fn is_lint_ref_type(ty: &Ty) -> bool {
if let TyRptr(Some(_), MutTy { ty: ref inner, mutbl: MutImmutable }) = ty.node {
if let TyPath(None, ref path) = inner.node {
if let TyPath(ref path) = inner.node {
return match_path(path, &paths::LINT);
}
}
@ -149,7 +149,7 @@ fn is_lint_ref_type(ty: &Ty) -> bool {
fn is_lint_array_type(ty: &Ty) -> bool {
if let TyPath(None, ref path) = ty.node {
if let TyPath(ref path) = ty.node {
match_path(path, &paths::LINT_ARRAY)
} else {
false

View File

@ -1,6 +1,7 @@
use reexport::*;
use rustc::hir::*;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::hir::def::Def;
use rustc::hir::map::Node;
use rustc::lint::{LintContext, LateContext, Level, Lint};
use rustc::session::Session;
@ -202,7 +203,15 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool
/// ```
/// match_path(path, &["std", "rt", "begin_unwind"])
/// ```
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
pub fn match_path(path: &QPath, segments: &[&str]) -> bool {
if let QPath::Resolved(_, ref path) = *path {
match_path_old(path, segments)
} else {
false
}
}
pub fn match_path_old(path: &Path, segments: &[&str]) -> bool {
path.segments.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.name == *b)
}
@ -283,8 +292,8 @@ pub fn implements_trait<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>,
}
/// Resolve the definition of a node from its `NodeId`.
pub fn resolve_node(cx: &LateContext, id: NodeId) -> Option<def::Def> {
cx.tcx.def_map.borrow().get(&id).map(|d| d.full_def())
pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: NodeId) -> def::Def {
cx.tcx.tables().qpath_def(qpath, id)
}
/// Match an `Expr` against a chain of methods, and return the matched `Expr`s.
@ -736,8 +745,8 @@ pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>, env: Node
/// Return whether a pattern is refutable.
pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool {
fn is_enum_variant(cx: &LateContext, did: NodeId) -> bool {
matches!(cx.tcx.def_map.borrow().get(&did).map(|d| d.full_def()), Some(def::Def::Variant(..)) | Some(def::Def::VariantCtor(..)))
fn is_enum_variant(cx: &LateContext, qpath: &QPath, did: NodeId) -> bool {
matches!(cx.tcx.tables().qpath_def(qpath, did), def::Def::Variant(..) | def::Def::VariantCtor(..))
}
fn are_refutable<'a, I: Iterator<Item=&'a Pat>>(cx: &LateContext, mut i: I) -> bool {
@ -748,17 +757,17 @@ pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool {
PatKind::Binding(..) | PatKind::Wild => false,
PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
PatKind::Lit(..) | PatKind::Range(..) => true,
PatKind::Path(..) => is_enum_variant(cx, pat.id),
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.id),
PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
PatKind::Struct(_, ref fields, _) => {
if is_enum_variant(cx, pat.id) {
PatKind::Struct(ref qpath, ref fields, _) => {
if is_enum_variant(cx, qpath, pat.id) {
true
} else {
are_refutable(cx, fields.iter().map(|field| &*field.node.pat))
}
}
PatKind::TupleStruct(_, ref pats, _) => {
if is_enum_variant(cx, pat.id) {
PatKind::TupleStruct(ref qpath, ref pats, _) => {
if is_enum_variant(cx, qpath, pat.id) {
true
} else {
are_refutable(cx, pats.iter().map(|pat| &**pat))
@ -793,3 +802,20 @@ pub fn remove_blocks(expr: &Expr) -> &Expr {
expr
}
}
pub fn opt_def_id(def: Def) -> Option<DefId> {
match def {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id) => {
Some(id)
}
Def::Label(..) |
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::Err => None,
}
}