mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
WIP compiles and doesn't crash (much) but tests are failing
This commit is contained in:
parent
f9fe50da1e
commit
59b0077565
@ -1,6 +1,9 @@
|
|||||||
# Change Log
|
# Change Log
|
||||||
All notable changes to this project will be documented in this file.
|
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
|
## 0.0.103 — 2016-11-25
|
||||||
* Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)*
|
* Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)*
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ impl LateLintPass for AttrPass {
|
|||||||
}
|
}
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemExternCrate(_) |
|
ItemExternCrate(_) |
|
||||||
ItemUse(_) => {
|
ItemUse(_, _) => {
|
||||||
for attr in &item.attrs {
|
for attr in &item.attrs {
|
||||||
if let MetaItemKind::List(ref lint_list) = attr.value.node {
|
if let MetaItemKind::List(ref lint_list) = attr.value.node {
|
||||||
match &*attr.name().as_str() {
|
match &*attr.name().as_str() {
|
||||||
@ -113,7 +113,7 @@ impl LateLintPass for AttrPass {
|
|||||||
// whitelist `unused_imports`
|
// whitelist `unused_imports`
|
||||||
for lint in lint_list {
|
for lint in lint_list {
|
||||||
if is_word(lint, "unused_imports") {
|
if is_word(lint, "unused_imports") {
|
||||||
if let ItemUse(_) = item.node {
|
if let ItemUse(_, _) = item.node {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,8 +193,8 @@ fn is_relevant_expr(cx: &LateContext, expr: &Expr) -> bool {
|
|||||||
ExprRet(Some(ref e)) => is_relevant_expr(cx, e),
|
ExprRet(Some(ref e)) => is_relevant_expr(cx, e),
|
||||||
ExprRet(None) | ExprBreak(_, None) => false,
|
ExprRet(None) | ExprBreak(_, None) => false,
|
||||||
ExprCall(ref path_expr, _) => {
|
ExprCall(ref path_expr, _) => {
|
||||||
if let ExprPath(..) = path_expr.node {
|
if let ExprPath(ref qpath) = path_expr.node {
|
||||||
let fun_id = resolve_node(cx, path_expr.id).expect("function should be resolved").def_id();
|
let fun_id = resolve_node(cx, qpath, path_expr.id).def_id();
|
||||||
!match_def_path(cx, fun_id, &paths::BEGIN_PANIC)
|
!match_def_path(cx, fun_id, &paths::BEGIN_PANIC)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::def::{Def, PathResolution};
|
use rustc::hir::def::Def;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc_const_eval::lookup_const_by_id;
|
use rustc_const_eval::lookup_const_by_id;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
@ -245,18 +245,13 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprPath(_, _) => {
|
ExprPath(ref qpath) => {
|
||||||
{
|
let def = cx.tcx.tables().qpath_def(qpath, lit.id);
|
||||||
// Important to let the borrow expire before the const lookup to avoid double
|
if let Def::Const(def_id) = def {
|
||||||
// borrowing.
|
lookup_const_by_id(cx.tcx, def_id, None).and_then(|(l, _ty)| fetch_int_literal(cx, l))
|
||||||
let def_map = cx.tcx.def_map.borrow();
|
} else {
|
||||||
match def_map.get(&lit.id) {
|
None
|
||||||
Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None))
|
|
||||||
.and_then(|(l, _ty)| fetch_int_literal(cx, l))
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ impl LintPass for BlackListedName {
|
|||||||
|
|
||||||
impl LateLintPass for BlackListedName {
|
impl LateLintPass for BlackListedName {
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
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()) {
|
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
BLACKLISTED_NAME,
|
BLACKLISTED_NAME,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#![allow(cast_possible_truncation)]
|
#![allow(cast_possible_truncation)]
|
||||||
|
|
||||||
use rustc::lint::LateContext;
|
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_eval::lookup_const_by_id;
|
||||||
use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
|
use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
@ -10,7 +10,7 @@ use std::cmp::PartialOrd;
|
|||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
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;
|
use syntax::ptr::P;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[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.
|
/// simple constant folding: Insert an expression, get a constant or none.
|
||||||
fn expr(&mut self, e: &Expr) -> Option<Constant> {
|
fn expr(&mut self, e: &Expr) -> Option<Constant> {
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprPath(_, _) => self.fetch_path(e),
|
ExprPath(ref qpath) => self.fetch_path(qpath, e.id),
|
||||||
ExprBlock(ref block) => self.block(block),
|
ExprBlock(ref block) => self.block(block),
|
||||||
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
|
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
|
||||||
ExprLit(ref lit) => Some(lit_to_constant(&lit.node)),
|
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
|
/// 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 {
|
if let Some(lcx) = self.lcx {
|
||||||
let mut maybe_id = None;
|
let def = lcx.tcx.tables().qpath_def(qpath, id);
|
||||||
if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) {
|
match def {
|
||||||
maybe_id = Some(id);
|
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
|
||||||
}
|
let substs = Some(lcx.tcx.tables().node_id_item_substs(id)
|
||||||
// separate if lets to avoid double borrowing the def_map
|
.unwrap_or_else(|| lcx.tcx.intern_substs(&[])));
|
||||||
if let Some(id) = maybe_id {
|
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, def_id, substs) {
|
||||||
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) {
|
let ret = self.expr(const_expr);
|
||||||
let ret = self.expr(const_expr);
|
if ret.is_some() {
|
||||||
if ret.is_some() {
|
self.needed_resolution = true;
|
||||||
self.needed_resolution = true;
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
return ret;
|
},
|
||||||
}
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -254,7 +254,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
|
|||||||
bindings_impl(cx, pat, map);
|
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()) {
|
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) {
|
||||||
v.insert(cx.tcx.tables().pat_ty(pat));
|
v.insert(cx.tcx.tables().pat_ty(pat));
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use rustc::ty;
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::paths;
|
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`
|
/// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
|
||||||
/// explicitly.
|
/// 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>,
|
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) {
|
hash_is_automatically_derived: bool) {
|
||||||
if_let_chain! {[
|
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 Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
|
||||||
], {
|
], {
|
||||||
let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);
|
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.
|
/// 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>) {
|
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 parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
|
||||||
let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs);
|
let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs);
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ impl LintPass for Pass {
|
|||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||||
if let ExprCall(ref path, ref args) = expr.node {
|
if let ExprCall(ref path, ref args) = expr.node {
|
||||||
if let ExprPath(None, _) = path.node {
|
if let ExprPath(ref qpath) = path.node {
|
||||||
let def_id = cx.tcx.expect_def(path.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
|
||||||
if match_def_path(cx, def_id, &paths::DROP) {
|
if match_def_path(cx, def_id, &paths::DROP) {
|
||||||
if args.len() != 1 {
|
if args.len() != 1 {
|
||||||
return;
|
return;
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::map::Node::NodeItem;
|
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray};
|
||||||
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext};
|
|
||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::span_lint;
|
use utils::span_lint;
|
||||||
@ -48,24 +47,9 @@ impl EnumGlobUse {
|
|||||||
if item.vis == Visibility::Public {
|
if item.vis == Visibility::Public {
|
||||||
return; // re-exports are fine
|
return; // re-exports are fine
|
||||||
}
|
}
|
||||||
if let ItemUse(ref item_use) = item.node {
|
if let ItemUse(ref path, UseKind::Glob) = item.node {
|
||||||
if let ViewPath_::ViewPathGlob(_) = item_use.node {
|
if let Def::Enum(_) = path.def {
|
||||||
if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) {
|
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,9 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
for (a1, a2) in decl.inputs.iter().zip(args) {
|
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?
|
// 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 p.segments.len() != 1 {
|
||||||
// If it's a proper path, it can't be a local variable
|
// If it's a proper path, it can't be a local variable
|
||||||
return;
|
return;
|
||||||
|
@ -61,16 +61,18 @@ impl LateLintPass for EvalOrderDependence {
|
|||||||
// Find a write to a local variable.
|
// Find a write to a local variable.
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
|
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
|
||||||
if let ExprPath(None, ref path) = lhs.node {
|
if let ExprPath(ref qpath) = lhs.node {
|
||||||
if path.segments.len() == 1 {
|
if let QPath::Resolved(_, ref path) = *qpath {
|
||||||
let var = cx.tcx.expect_def(lhs.id).def_id();
|
if path.segments.len() == 1 {
|
||||||
let mut visitor = ReadVisitor {
|
let var = cx.tcx.tables().qpath_def(qpath, lhs.id).def_id();
|
||||||
cx: cx,
|
let mut visitor = ReadVisitor {
|
||||||
var: var,
|
cx: cx,
|
||||||
write_expr: expr,
|
var: var,
|
||||||
last_expr: expr,
|
write_expr: expr,
|
||||||
};
|
last_expr: expr,
|
||||||
check_for_unsequenced_reads(&mut visitor);
|
};
|
||||||
|
check_for_unsequenced_reads(&mut visitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,19 +295,21 @@ impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprPath(None, ref path) => {
|
ExprPath(ref qpath) => {
|
||||||
if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var {
|
if let QPath::Resolved(None, ref path) = *qpath {
|
||||||
if is_in_assignment_position(self.cx, expr) {
|
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
|
||||||
// This is a write, not a read.
|
if is_in_assignment_position(self.cx, expr) {
|
||||||
} else {
|
// This is a write, not a read.
|
||||||
span_note_and_lint(
|
} else {
|
||||||
self.cx,
|
span_note_and_lint(
|
||||||
EVAL_ORDER_DEPENDENCE,
|
self.cx,
|
||||||
expr.span,
|
EVAL_ORDER_DEPENDENCE,
|
||||||
"unsequenced read of a variable",
|
expr.span,
|
||||||
self.write_expr.span,
|
"unsequenced read of a variable",
|
||||||
"whether read occurs before this write depends on evaluation order"
|
self.write_expr.span,
|
||||||
);
|
"whether read occurs before this write depends on evaluation order"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,9 @@ impl LateLintPass for Pass {
|
|||||||
// `format!("{}", foo)` expansion
|
// `format!("{}", foo)` expansion
|
||||||
ExprCall(ref fun, ref args) => {
|
ExprCall(ref fun, ref args) => {
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let ExprPath(..) = fun.node,
|
let ExprPath(ref qpath) = fun.node,
|
||||||
args.len() == 2,
|
args.len() == 2,
|
||||||
let Some(fun) = resolve_node(cx, fun.id),
|
match_def_path(cx, resolve_node(cx, qpath, fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
|
||||||
match_def_path(cx, fun.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
|
|
||||||
// ensure the format string is `"{..}"` with only one argument and no text
|
// ensure the format string is `"{..}"` with only one argument and no text
|
||||||
check_static_str(cx, &args[0]),
|
check_static_str(cx, &args[0]),
|
||||||
// ensure the format argument is `{}` ie. Display with no fancy option
|
// ensure the format argument is `{}` ie. Display with no fancy option
|
||||||
@ -129,9 +128,8 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
|
|||||||
exprs.len() == 1,
|
exprs.len() == 1,
|
||||||
let ExprCall(_, ref args) = exprs[0].node,
|
let ExprCall(_, ref args) = exprs[0].node,
|
||||||
args.len() == 2,
|
args.len() == 2,
|
||||||
let ExprPath(None, _) = args[1].node,
|
let ExprPath(ref qpath) = args[1].node,
|
||||||
let Some(fun) = resolve_node(cx, args[1].id),
|
match_def_path(cx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD),
|
||||||
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD),
|
|
||||||
], {
|
], {
|
||||||
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));
|
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));
|
||||||
|
|
||||||
|
@ -138,9 +138,9 @@ impl Functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
|
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) {
|
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
|
||||||
cx.tcx.def_map.borrow().get(&arg.pat.id).map(|pr| pr.full_def().def_id())
|
Some(def_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -183,8 +183,9 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
|
||||||
fn check_arg(&self, ptr: &hir::Expr) {
|
fn check_arg(&self, ptr: &hir::Expr) {
|
||||||
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) {
|
if let hir::ExprPath(ref qpath) = ptr.node {
|
||||||
if self.ptrs.contains(&def.full_def().def_id()) {
|
let def = self.cx.tcx.tables().qpath_def(qpath, ptr.id);
|
||||||
|
if self.ptrs.contains(&def.def_id()) {
|
||||||
span_lint(self.cx,
|
span_lint(self.cx,
|
||||||
NOT_UNSAFE_PTR_ARG_DEREF,
|
NOT_UNSAFE_PTR_ARG_DEREF,
|
||||||
ptr.span,
|
ptr.span,
|
||||||
|
@ -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()"
|
"is_none()"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +65,18 @@ impl LateLintPass for LetIfSeq {
|
|||||||
let Some(expr) = it.peek(),
|
let Some(expr) = it.peek(),
|
||||||
let hir::StmtDecl(ref decl, _) = stmt.node,
|
let hir::StmtDecl(ref decl, _) = stmt.node,
|
||||||
let hir::DeclLocal(ref decl) = decl.node,
|
let hir::DeclLocal(ref decl) = decl.node,
|
||||||
let hir::PatKind::Binding(mode, ref name, None) = decl.pat.node,
|
let hir::PatKind::Binding(mode, def_id, ref name, None) = decl.pat.node,
|
||||||
let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id),
|
|
||||||
let hir::StmtExpr(ref if_, _) = expr.node,
|
let hir::StmtExpr(ref if_, _) = expr.node,
|
||||||
let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
|
let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
|
||||||
!used_in_expr(cx, def.full_def().def_id(), cond),
|
!used_in_expr(cx, def_id, cond),
|
||||||
let Some(value) = check_assign(cx, def.full_def().def_id(), then),
|
let Some(value) = check_assign(cx, def_id, then),
|
||||||
!used_in_expr(cx, def.full_def().def_id(), value),
|
!used_in_expr(cx, def_id, value),
|
||||||
], {
|
], {
|
||||||
let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);
|
let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);
|
||||||
|
|
||||||
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
|
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
|
||||||
if let hir::ExprBlock(ref else_) = else_.node {
|
if let hir::ExprBlock(ref else_) = else_.node {
|
||||||
if let Some(default) = check_assign(cx, def.full_def().def_id(), else_) {
|
if let Some(default) = check_assign(cx, def_id, else_) {
|
||||||
(else_.stmts.len() > 1, default)
|
(else_.stmts.len() > 1, default)
|
||||||
} else if let Some(ref default) = decl.init {
|
} else if let Some(ref default) = decl.init {
|
||||||
(true, &**default)
|
(true, &**default)
|
||||||
@ -137,9 +136,8 @@ struct UsedVisitor<'a, 'tcx: 'a> {
|
|||||||
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
|
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let hir::ExprPath(None, _) = expr.node,
|
let hir::ExprPath(ref qpath) = expr.node,
|
||||||
let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id),
|
self.id == self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id(),
|
||||||
self.id == def.full_def().def_id(),
|
|
||||||
], {
|
], {
|
||||||
self.used = true;
|
self.used = true;
|
||||||
return;
|
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 Some(expr) = block.stmts.iter().last(),
|
||||||
let hir::StmtSemi(ref expr, _) = expr.node,
|
let hir::StmtSemi(ref expr, _) = expr.node,
|
||||||
let hir::ExprAssign(ref var, ref value) = expr.node,
|
let hir::ExprAssign(ref var, ref value) = expr.node,
|
||||||
let hir::ExprPath(None, _) = var.node,
|
let hir::ExprPath(ref qpath) = var.node,
|
||||||
let Some(def) = cx.tcx.def_map.borrow().get(&var.id),
|
decl == cx.tcx.tables().qpath_def(qpath, var.id).def_id(),
|
||||||
decl == def.full_def().def_id(),
|
|
||||||
], {
|
], {
|
||||||
let mut v = UsedVisitor {
|
let mut v = UsedVisitor {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
|
@ -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_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_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 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 mem_forget::MemForget);
|
||||||
reg.register_late_lint_pass(box arithmetic::Arithmetic::default());
|
reg.register_late_lint_pass(box arithmetic::Arithmetic::default());
|
||||||
reg.register_late_lint_pass(box assign_ops::AssignOps);
|
reg.register_late_lint_pass(box assign_ops::AssignOps);
|
||||||
|
@ -239,12 +239,12 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
|||||||
self.lts
|
self.lts
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) {
|
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
|
||||||
let last_path_segment = path.segments.last().map(|s| &s.parameters);
|
if let QPath::Resolved(_, ref path) = *qpath {
|
||||||
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
|
let last_path_segment = path.segments.last().map(|s| &s.parameters);
|
||||||
if params.lifetimes.is_empty() {
|
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
|
||||||
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) {
|
if params.lifetimes.is_empty() {
|
||||||
match def {
|
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
|
||||||
Def::TyAlias(def_id) |
|
Def::TyAlias(def_id) |
|
||||||
Def::Struct(def_id) => {
|
Def::Struct(def_id) => {
|
||||||
let generics = self.cx.tcx.item_generics(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, _) => {
|
TyRptr(None, _) => {
|
||||||
self.record(&None);
|
self.record(&None);
|
||||||
}
|
}
|
||||||
TyPath(_, ref path) => {
|
TyPath(ref path) => {
|
||||||
self.collect_anonymous_lifetimes(path, ty);
|
self.collect_anonymous_lifetimes(path, ty);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -366,26 +366,28 @@ impl LateLintPass for Pass {
|
|||||||
}
|
}
|
||||||
if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node {
|
if let ExprMatch(ref match_expr, ref arms, MatchSource::WhileLetDesugar) = expr.node {
|
||||||
let pat = &arms[0].pats[0].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) {
|
&ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) {
|
||||||
let iter_expr = &method_args[0];
|
let iter_expr = &method_args[0];
|
||||||
if let Some(lhs_constructor) = path.segments.last() {
|
if let QPath::Resolved(_, ref path) = *qpath {
|
||||||
if &*method_name.node.as_str() == "next" &&
|
if let Some(lhs_constructor) = path.segments.last() {
|
||||||
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
|
if &*method_name.node.as_str() == "next" &&
|
||||||
&*lhs_constructor.name.as_str() == "Some" &&
|
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
|
||||||
!is_refutable(cx, &pat_args[0]) &&
|
&*lhs_constructor.name.as_str() == "Some" &&
|
||||||
!is_iterator_used_after_while_let(cx, iter_expr) {
|
!is_refutable(cx, &pat_args[0]) &&
|
||||||
let iterator = snippet(cx, method_args[0].span, "_");
|
!is_iterator_used_after_while_let(cx, iter_expr) {
|
||||||
let loop_var = snippet(cx, pat_args[0].span, "_");
|
let iterator = snippet(cx, method_args[0].span, "_");
|
||||||
span_lint_and_then(cx,
|
let loop_var = snippet(cx, pat_args[0].span, "_");
|
||||||
WHILE_LET_ON_ITERATOR,
|
span_lint_and_then(cx,
|
||||||
expr.span,
|
WHILE_LET_ON_ITERATOR,
|
||||||
"this loop could be written as a `for` loop",
|
expr.span,
|
||||||
|db| {
|
"this loop could be written as a `for` loop",
|
||||||
db.span_suggestion(expr.span,
|
|db| {
|
||||||
"try",
|
db.span_suggestion(expr.span,
|
||||||
format!("for {} in {} {{ .. }}", loop_var, iterator));
|
"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) {
|
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) {
|
if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) {
|
||||||
// the var must be a single name
|
// 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 {
|
let mut visitor = VarVisitor {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
var: cx.tcx.expect_def(pat.id).def_id(),
|
var: def_id,
|
||||||
indexed: HashMap::new(),
|
indexed: HashMap::new(),
|
||||||
nonindex: false,
|
nonindex: false,
|
||||||
};
|
};
|
||||||
@ -510,7 +512,7 @@ fn is_len_call(expr: &Expr, var: &Name) -> bool {
|
|||||||
let ExprMethodCall(method, _, ref len_args) = expr.node,
|
let ExprMethodCall(method, _, ref len_args) = expr.node,
|
||||||
len_args.len() == 1,
|
len_args.len() == 1,
|
||||||
&*method.node.as_str() == "len",
|
&*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.len() == 1,
|
||||||
&path.segments[0].name == var
|
&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 {
|
fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
|
||||||
match *pat {
|
match *pat {
|
||||||
PatKind::Wild => true,
|
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 {
|
let mut visitor = UsedVisitor {
|
||||||
var: ident.node,
|
var: ident.node,
|
||||||
used: false,
|
used: false,
|
||||||
@ -751,7 +753,7 @@ struct UsedVisitor {
|
|||||||
|
|
||||||
impl<'a> Visitor<'a> for UsedVisitor {
|
impl<'a> Visitor<'a> for UsedVisitor {
|
||||||
fn visit_expr(&mut self, expr: &Expr) {
|
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 {
|
if path.segments.len() == 1 && path.segments[0].name == self.var {
|
||||||
self.used = true;
|
self.used = true;
|
||||||
return;
|
return;
|
||||||
@ -771,20 +773,21 @@ struct VarVisitor<'v, 't: 'v> {
|
|||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
|
impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'v Expr) {
|
||||||
if let ExprPath(None, ref path) = expr.node {
|
if let ExprPath(ref qpath) = expr.node {
|
||||||
if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var {
|
if let QPath::Resolved(None, ref path) = *qpath {
|
||||||
// we are referencing our variable! now check if it's as an index
|
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
|
||||||
if_let_chain! {[
|
// we are referencing our variable! now check if it's as an index
|
||||||
let Some(parexpr) = get_parent_expr(self.cx, expr),
|
if_let_chain! {[
|
||||||
let ExprIndex(ref seqexpr, _) = parexpr.node,
|
let Some(parexpr) = get_parent_expr(self.cx, expr),
|
||||||
let ExprPath(None, ref seqvar) = seqexpr.node,
|
let ExprIndex(ref seqexpr, _) = parexpr.node,
|
||||||
seqvar.segments.len() == 1
|
let ExprPath(ref seqpath) = seqexpr.node,
|
||||||
], {
|
let QPath::Resolved(None, ref seqvar) = *seqpath,
|
||||||
let def_map = self.cx.tcx.def_map.borrow();
|
seqvar.segments.len() == 1
|
||||||
if let Some(def) = def_map.get(&seqexpr.id) {
|
], {
|
||||||
match def.base_def {
|
let def = self.cx.tcx.tables().qpath_def(seqpath, seqexpr.id);
|
||||||
|
match def {
|
||||||
Def::Local(..) | Def::Upvar(..) => {
|
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 node_id = self.cx.tcx.map.as_local_node_id(def_id).unwrap();
|
||||||
|
|
||||||
let extent = self.cx.tcx.region_maps.var_scope(node_id);
|
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
|
||||||
// we are not indexing anything, record that
|
self.nonindex = true;
|
||||||
self.nonindex = true;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
@ -1002,7 +1005,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
|
|||||||
// Look for declarations of the variable
|
// Look for declarations of the variable
|
||||||
if let DeclLocal(ref local) = decl.node {
|
if let DeclLocal(ref local) = decl.node {
|
||||||
if local.pat.id == self.var_id {
|
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.name = Some(ident.node);
|
||||||
|
|
||||||
self.state = if let Some(ref init) = local.init {
|
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> {
|
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 ExprPath(ref qpath) = expr.node {
|
||||||
if let Def::Local(def_id) = path_res.base_def {
|
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");
|
let node_id = cx.tcx.map.as_local_node_id(def_id).expect("That DefId should be valid");
|
||||||
return Some(node_id);
|
return Some(node_id);
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ impl LateLintPass for Pass {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
ExprPath(_, ref path) => {
|
ExprPath(ref path) => {
|
||||||
if match_path(path, &paths::CLONE) {
|
if match_path(path, &paths::CLONE) {
|
||||||
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
|
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
|
||||||
span_help_and_lint(cx,
|
span_help_and_lint(cx,
|
||||||
@ -85,7 +85,7 @@ impl LateLintPass for Pass {
|
|||||||
|
|
||||||
fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
|
fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprPath(None, ref path) => {
|
ExprPath(QPath::Resolved(None, ref path)) => {
|
||||||
let arg_segment = [PathSegment {
|
let arg_segment = [PathSegment {
|
||||||
name: id,
|
name: id,
|
||||||
parameters: PathParameters::none(),
|
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> {
|
fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
|
||||||
match pat.node {
|
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),
|
PatKind::Ref(ref subpat, _) => get_arg_name(subpat),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -210,8 +210,8 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
|
|||||||
}
|
}
|
||||||
path.to_string()
|
path.to_string()
|
||||||
}
|
}
|
||||||
PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(),
|
PatKind::Binding(BindByValue(MutImmutable), _, ident, None) => ident.node.to_string(),
|
||||||
PatKind::Path(None, ref path) => path.to_string(),
|
PatKind::Path(ref path) => path.to_string(),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ impl LintPass for MemForget {
|
|||||||
impl LateLintPass for MemForget {
|
impl LateLintPass for MemForget {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
||||||
if let ExprCall(ref path_expr, ref args) = e.node {
|
if let ExprCall(ref path_expr, ref args) = e.node {
|
||||||
if let ExprPath(None, _) = path_expr.node {
|
if let ExprPath(ref qpath) = path_expr.node {
|
||||||
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
||||||
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
|
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
|
||||||
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);
|
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);
|
||||||
|
|
||||||
|
@ -701,7 +701,7 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if name == "unwrap_or" {
|
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
|
let path: &str = &path.segments
|
||||||
.last()
|
.last()
|
||||||
.expect("A path must have at least one segment")
|
.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!{[
|
if_let_chain!{[
|
||||||
let hir::ExprCall(ref fun, ref args) = new.node,
|
let hir::ExprCall(ref fun, ref args) = new.node,
|
||||||
args.len() == 1,
|
args.len() == 1,
|
||||||
let hir::ExprPath(None, ref path) = fun.node,
|
let hir::ExprPath(ref path) = fun.node,
|
||||||
match_path(path, &paths::CSTRING_NEW),
|
match_path(path, &paths::CSTRING_NEW),
|
||||||
], {
|
], {
|
||||||
span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span,
|
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 Some(args) = method_chain_args(chain, &["chars", "next"]),
|
||||||
let hir::ExprCall(ref fun, ref arg_char) = other.node,
|
let hir::ExprCall(ref fun, ref arg_char) = other.node,
|
||||||
arg_char.len() == 1,
|
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"
|
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]));
|
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 {
|
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"])
|
match_path(p, &["bool"])
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -61,8 +61,8 @@ enum MinMax {
|
|||||||
|
|
||||||
fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
|
fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
|
||||||
if let ExprCall(ref path, ref args) = expr.node {
|
if let ExprCall(ref path, ref args) = expr.node {
|
||||||
if let ExprPath(None, _) = path.node {
|
if let ExprPath(ref qpath) = path.node {
|
||||||
let def_id = cx.tcx.expect_def(path.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
|
||||||
|
|
||||||
if match_def_path(cx, def_id, &paths::CMP_MIN) {
|
if match_def_path(cx, def_id, &paths::CMP_MIN) {
|
||||||
fetch_const(args, MinMax::Min)
|
fetch_const(args, MinMax::Min)
|
||||||
|
@ -173,7 +173,7 @@ impl LateLintPass for Pass {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
|
if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
TOPLEVEL_REF_ARG,
|
TOPLEVEL_REF_ARG,
|
||||||
arg.pat.span,
|
arg.pat.span,
|
||||||
@ -186,7 +186,7 @@ impl LateLintPass for Pass {
|
|||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let StmtDecl(ref d, _) = s.node,
|
let StmtDecl(ref d, _) = s.node,
|
||||||
let DeclLocal(ref l) = d.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 Some(ref init) = l.init
|
||||||
], {
|
], {
|
||||||
let init = Sugg::hir(cx, 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 {
|
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
|
||||||
let op = cmp.node;
|
let op = cmp.node;
|
||||||
if op.is_comparison() {
|
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);
|
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_nan(cx, path, expr.span);
|
||||||
}
|
}
|
||||||
check_to_owned(cx, left, right, true, cmp.span);
|
check_to_owned(cx, left, right, true, cmp.span);
|
||||||
@ -262,19 +262,23 @@ impl LateLintPass for Pass {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let binding = match expr.node {
|
let binding = match expr.node {
|
||||||
ExprPath(_, ref path) => {
|
ExprPath(ref qpath) => {
|
||||||
let binding = path.segments
|
if let QPath::Resolved(_, ref path) = *qpath {
|
||||||
.last()
|
let binding = path.segments
|
||||||
.expect("path should always have at least one segment")
|
.last()
|
||||||
.name
|
.expect("path should always have at least one segment")
|
||||||
.as_str();
|
.name
|
||||||
if binding.starts_with('_') &&
|
.as_str();
|
||||||
!binding.starts_with("__") &&
|
if binding.starts_with('_') &&
|
||||||
&*binding != "_result" && // FIXME: #944
|
!binding.starts_with("__") &&
|
||||||
is_used(cx, expr) &&
|
&*binding != "_result" && // FIXME: #944
|
||||||
// don't lint if the declaration is in a macro
|
is_used(cx, expr) &&
|
||||||
non_macro_local(cx, &cx.tcx.expect_def(expr.id)) {
|
// don't lint if the declaration is in a macro
|
||||||
Some(binding)
|
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
|
||||||
|
Some(binding)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -299,7 +303,7 @@ impl LateLintPass for Pass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
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 {
|
if right.node == PatKind::Wild {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
REDUNDANT_PATTERN,
|
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 => {
|
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"]) {
|
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) {
|
||||||
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
|
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,7 +42,7 @@ impl LateLintPass for UnnecessaryMutPassed {
|
|||||||
.expect("A function with an unknown type is called. \
|
.expect("A function with an unknown type is called. \
|
||||||
If this happened, the compiler would have \
|
If this happened, the compiler would have \
|
||||||
aborted the compilation long ago");
|
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());
|
check_arguments(cx, arguments, function_type, &path.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl LateLintPass for NeedlessBorrow {
|
|||||||
if in_macro(cx, pat.span) {
|
if in_macro(cx, pat.span) {
|
||||||
return;
|
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 let ty::TyRef(_, ref tam) = cx.tcx.tables().pat_ty(pat).sty {
|
||||||
if tam.mutbl == MutImmutable {
|
if tam.mutbl == MutImmutable {
|
||||||
if let ty::TyRef(..) = tam.ty.sty {
|
if let ty::TyRef(..) = tam.ty.sty {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
|
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 rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource};
|
||||||
use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then};
|
use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@ -68,13 +68,17 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr_::ExprCall(ref callee, ref args) => {
|
Expr_::ExprCall(ref callee, ref args) => {
|
||||||
let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
|
if let Expr_::ExprPath(ref qpath) = callee.node {
|
||||||
match def {
|
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
|
||||||
Some(Def::Struct(..)) |
|
match def {
|
||||||
Some(Def::Variant(..)) |
|
Def::Struct(..) |
|
||||||
Some(Def::StructCtor(..)) |
|
Def::Variant(..) |
|
||||||
Some(Def::VariantCtor(..)) => args.iter().all(|arg| has_no_effect(cx, arg)),
|
Def::StructCtor(..) |
|
||||||
_ => false,
|
Def::VariantCtor(..) => args.iter().all(|arg| has_no_effect(cx, arg)),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr_::ExprBlock(ref block) => {
|
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())
|
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
|
||||||
}
|
}
|
||||||
Expr_::ExprCall(ref callee, ref args) => {
|
Expr_::ExprCall(ref callee, ref args) => {
|
||||||
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
|
if let Expr_::ExprPath(ref qpath) = callee.node {
|
||||||
Some(Def::Struct(..)) |
|
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
|
||||||
Some(Def::Variant(..)) |
|
match def {
|
||||||
Some(Def::StructCtor(..)) |
|
Def::Struct(..) |
|
||||||
Some(Def::VariantCtor(..)) => Some(args.iter().collect()),
|
Def::Variant(..) |
|
||||||
_ => None,
|
Def::StructCtor(..) |
|
||||||
|
Def::VariantCtor(..) => Some(args.iter().collect()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr_::ExprBlock(ref block) => {
|
Expr_::ExprBlock(ref block) => {
|
||||||
|
@ -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 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 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 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;
|
method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;
|
||||||
|
|
||||||
], {
|
], {
|
||||||
|
@ -35,9 +35,9 @@ impl LateLintPass for OverflowCheckConditional {
|
|||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
||||||
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
|
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
|
||||||
let Expr_::ExprPath(_,ref path1) = ident1.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
|
||||||
let Expr_::ExprPath(_, ref path2) = ident2.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
|
||||||
let Expr_::ExprPath(_, ref path3) = second.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node,
|
||||||
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
||||||
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
||||||
cx.tcx.tables().expr_ty(ident2).is_integral()
|
cx.tcx.tables().expr_ty(ident2).is_integral()
|
||||||
@ -57,9 +57,9 @@ impl LateLintPass for OverflowCheckConditional {
|
|||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
||||||
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node,
|
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node,
|
||||||
let Expr_::ExprPath(_,ref path1) = ident1.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
|
||||||
let Expr_::ExprPath(_, ref path2) = ident2.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
|
||||||
let Expr_::ExprPath(_, ref path3) = first.node,
|
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node,
|
||||||
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
|
||||||
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
cx.tcx.tables().expr_ty(ident1).is_integral(),
|
||||||
cx.tcx.tables().expr_ty(ident2).is_integral()
|
cx.tcx.tables().expr_ty(ident2).is_integral()
|
||||||
|
@ -39,9 +39,8 @@ impl LateLintPass for Pass {
|
|||||||
let Some(ref ex) = block.expr,
|
let Some(ref ex) = block.expr,
|
||||||
let ExprCall(ref fun, ref params) = ex.node,
|
let ExprCall(ref fun, ref params) = ex.node,
|
||||||
params.len() == 2,
|
params.len() == 2,
|
||||||
let ExprPath(None, _) = fun.node,
|
let ExprPath(ref qpath) = fun.node,
|
||||||
let Some(fun) = resolve_node(cx, fun.id),
|
match_def_path(cx, resolve_node(cx, qpath, fun.id).def_id(), &paths::BEGIN_PANIC),
|
||||||
match_def_path(cx, fun.def_id(), &paths::BEGIN_PANIC),
|
|
||||||
let ExprLit(ref lit) = params[0].node,
|
let ExprLit(ref lit) = params[0].node,
|
||||||
is_direct_expn_of(cx, params[0].span, "panic").is_some(),
|
is_direct_expn_of(cx, params[0].span, "panic").is_some(),
|
||||||
let LitKind::Str(ref string, _) = lit.node,
|
let LitKind::Str(ref string, _) = lit.node,
|
||||||
|
@ -40,7 +40,7 @@ impl LateLintPass for Pass {
|
|||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
|
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
|
||||||
!is_automatically_derived(&*item.attrs),
|
!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 {
|
for impl_item in impl_items {
|
||||||
if &*impl_item.name.as_str() == "ne" {
|
if &*impl_item.name.as_str() == "ne" {
|
||||||
|
@ -2,7 +2,7 @@ use rustc::hir::*;
|
|||||||
use rustc::hir::map::Node::{NodeItem, NodeImplItem};
|
use rustc::hir::map::Node::{NodeItem, NodeImplItem};
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use utils::paths;
|
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;
|
use format::get_argument_fmtstr_parts;
|
||||||
|
|
||||||
/// **What it does:** This lint warns when you using `print!()` with a format string that
|
/// **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) {
|
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ExprCall(ref fun, ref args) = expr.node,
|
let ExprCall(ref fun, ref args) = expr.node,
|
||||||
let ExprPath(..) = fun.node,
|
let ExprPath(ref qpath) = fun.node,
|
||||||
let Some(fun) = resolve_node(cx, fun.id),
|
|
||||||
], {
|
], {
|
||||||
|
let fun = resolve_node(cx, qpath, fun.id);
|
||||||
let fun_id = fun.def_id();
|
let fun_id = fun.def_id();
|
||||||
|
|
||||||
// Search for `std::io::_print(..)` which is unique in a
|
// Search for `std::io::_print(..)` which is unique in a
|
||||||
@ -93,9 +93,8 @@ impl LateLintPass for Pass {
|
|||||||
// ensure we're calling Arguments::new_v1
|
// ensure we're calling Arguments::new_v1
|
||||||
args.len() == 1,
|
args.len() == 1,
|
||||||
let ExprCall(ref args_fun, ref args_args) = args[0].node,
|
let ExprCall(ref args_fun, ref args_args) = args[0].node,
|
||||||
let ExprPath(..) = args_fun.node,
|
let ExprPath(ref qpath) = args_fun.node,
|
||||||
let Some(def) = resolve_node(cx, args_fun.id),
|
match_def_path(cx, resolve_node(cx, qpath, args_fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
|
||||||
match_def_path(cx, def.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
|
|
||||||
args_args.len() == 2,
|
args_args.len() == 2,
|
||||||
let ExprAddrOf(_, ref match_expr) = args_args[1].node,
|
let ExprAddrOf(_, ref match_expr) = args_args[1].node,
|
||||||
let ExprMatch(ref args, _, _) = match_expr.node,
|
let ExprMatch(ref args, _, _) = match_expr.node,
|
||||||
@ -121,8 +120,8 @@ impl LateLintPass for Pass {
|
|||||||
// Search for something like
|
// Search for something like
|
||||||
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
|
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
|
||||||
else if args.len() == 2 && match_def_path(cx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
|
else if args.len() == 2 && match_def_path(cx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
|
||||||
if let ExprPath(None, _) = args[1].node {
|
if let ExprPath(ref qpath) = args[1].node {
|
||||||
let def_id = resolve_node(cx, args[1].id).unwrap().def_id();
|
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) &&
|
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() {
|
is_expn_of(cx, expr.span, "panic").is_none() {
|
||||||
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
|
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
|
||||||
@ -141,7 +140,7 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
|
|||||||
// `Debug` impl
|
// `Debug` impl
|
||||||
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
|
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
|
||||||
if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
|
if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
|
||||||
return match_path(&tr.path, &["Debug"]);
|
return match_path_old(&tr.path, &["Debug"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ impl LateLintPass for PointerPass {
|
|||||||
check_fn(cx, &sig.decl, item.id);
|
check_fn(cx, &sig.decl, item.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||||
if let ExprBinary(ref op, ref l, ref r) = expr.node {
|
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)) {
|
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 {
|
fn is_null_path(expr: &Expr) -> bool {
|
||||||
if let ExprCall(ref pathexp, ref args) = expr.node {
|
if let ExprCall(ref pathexp, ref args) = expr.node {
|
||||||
if args.is_empty() {
|
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)
|
return match_path(path, &paths::PTR_NULL) || match_path(path, &paths::PTR_NULL_MUT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,15 +73,19 @@ impl LateLintPass for StepByZero {
|
|||||||
let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node,
|
let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node,
|
||||||
&*len_name.as_str() == "len" && len_args.len() == 1,
|
&*len_name.as_str() == "len" && len_args.len() == 1,
|
||||||
// .iter() and .len() called on same Path
|
// .iter() and .len() called on same Path
|
||||||
let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node,
|
let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node,
|
||||||
let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node,
|
let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node,
|
||||||
iter_path == len_path
|
iter_path == len_path
|
||||||
], {
|
], {
|
||||||
span_lint(cx,
|
let Path { segments: ref iter_path, .. } = **iter_path;
|
||||||
RANGE_ZIP_WITH_LEN,
|
let Path { segments: ref len_path, .. } = **len_path;
|
||||||
expr.span,
|
if iter_path == len_path {
|
||||||
&format!("It is more idiomatic to use {}.iter().enumerate()",
|
span_lint(cx,
|
||||||
snippet(cx, iter_args[0].span, "_")));
|
RANGE_ZIP_WITH_LEN,
|
||||||
|
expr.span,
|
||||||
|
&format!("It is more idiomatic to use {}.iter().enumerate()",
|
||||||
|
snippet(cx, iter_args[0].span, "_")));
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,10 +115,10 @@ impl LateLintPass for Pass {
|
|||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let ExprCall(ref fun, ref args) = expr.node,
|
let ExprCall(ref fun, ref args) = expr.node,
|
||||||
|
let ExprPath(ref qpath) = fun.node,
|
||||||
args.len() == 1,
|
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) ||
|
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
|
||||||
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
|
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
|
||||||
check_regex(cx, &args[0], true);
|
check_regex(cx, &args[0], true);
|
||||||
|
@ -29,7 +29,7 @@ impl LintPass for Serde {
|
|||||||
impl LateLintPass for Serde {
|
impl LateLintPass for Serde {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
||||||
if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node {
|
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 let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
|
||||||
if did == visit_did {
|
if did == visit_did {
|
||||||
let mut seen_str = None;
|
let mut seen_str = None;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::def::Def;
|
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, FnKind};
|
use rustc::hir::intravisit::{Visitor, FnKind};
|
||||||
|
use rustc::ty;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{higher, in_external_macro, snippet, span_lint_and_then};
|
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) {
|
fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
|
||||||
let mut bindings = Vec::new();
|
let mut bindings = Vec::new();
|
||||||
for arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
if let PatKind::Binding(_, ident, _) = arg.pat.node {
|
if let PatKind::Binding(_, _, ident, _) = arg.pat.node {
|
||||||
bindings.push((ident.node, ident.span))
|
bindings.push((ident.node, ident.span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,10 +135,10 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_binding(cx: &LateContext, pat: &Pat) -> bool {
|
fn is_binding(cx: &LateContext, pat_id: NodeId) -> bool {
|
||||||
match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
|
let var_ty = cx.tcx.tables().node_id_to_type(pat_id);
|
||||||
Some(Def::Variant(..)) |
|
match var_ty.sty {
|
||||||
Some(Def::Struct(..)) => false,
|
ty::TyAdt(..) => false,
|
||||||
_ => true,
|
_ => 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)>) {
|
fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) {
|
||||||
// TODO: match more stuff / destructuring
|
// TODO: match more stuff / destructuring
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Binding(_, ref ident, ref inner) => {
|
PatKind::Binding(_, _, ref ident, ref inner) => {
|
||||||
let name = ident.node;
|
let name = ident.node;
|
||||||
if is_binding(cx, pat) {
|
if is_binding(cx, pat.id) {
|
||||||
let mut new_binding = true;
|
let mut new_binding = true;
|
||||||
for tup in bindings.iter_mut() {
|
for tup in bindings.iter_mut() {
|
||||||
if tup.0 == name {
|
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))
|
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),
|
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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
|||||||
let StmtDecl(ref tmp, _) = w[0].node,
|
let StmtDecl(ref tmp, _) = w[0].node,
|
||||||
let DeclLocal(ref tmp) = tmp.node,
|
let DeclLocal(ref tmp) = tmp.node,
|
||||||
let Some(ref tmp_init) = tmp.init,
|
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();
|
// foo() = bar();
|
||||||
let StmtSemi(ref first, _) = w[1].node,
|
let StmtSemi(ref first, _) = w[1].node,
|
||||||
@ -74,7 +74,7 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
|||||||
// bar() = t;
|
// bar() = t;
|
||||||
let StmtSemi(ref second, _) = w[2].node,
|
let StmtSemi(ref second, _) = w[2].node,
|
||||||
let ExprAssign(ref lhs2, ref rhs2) = second.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,
|
rhs2.segments.len() == 1,
|
||||||
|
|
||||||
tmp_name.node.as_str() == rhs2.segments[0].name.as_str(),
|
tmp_name.node.as_str() == rhs2.segments[0].name.as_str(),
|
||||||
|
@ -87,8 +87,8 @@ impl LintPass for Transmute {
|
|||||||
impl LateLintPass for Transmute {
|
impl LateLintPass for Transmute {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
||||||
if let ExprCall(ref path_expr, ref args) = e.node {
|
if let ExprCall(ref path_expr, ref args) = e.node {
|
||||||
if let ExprPath(None, ref path) = path_expr.node {
|
if let ExprPath(ref qpath) = path_expr.node {
|
||||||
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
||||||
|
|
||||||
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
|
if match_def_path(cx, def_id, &paths::TRANSMUTE) {
|
||||||
let from_ty = cx.tcx.tables().expr_ty(&args[0]);
|
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 {
|
let arg = if from_pty.ty == to_rty.ty {
|
||||||
arg
|
arg
|
||||||
} else {
|
} 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());
|
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
|
/// 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 `'_`
|
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
|
||||||
/// lifetime, but it should be rare.
|
/// 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!{[
|
if_let_chain!{[
|
||||||
|
let QPath::Resolved(_, ref path) = *path,
|
||||||
let Some(seg) = path.segments.last(),
|
let Some(seg) = path.segments.last(),
|
||||||
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
|
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
|
||||||
let Some(to_ty) = ang.types.get(1),
|
let Some(to_ty) = ang.types.get(1),
|
||||||
|
@ -7,7 +7,7 @@ use std::cmp::Ordering;
|
|||||||
use syntax::ast::{IntTy, UintTy, FloatTy};
|
use syntax::ast::{IntTy, UintTy, FloatTy};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet,
|
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;
|
use utils::paths;
|
||||||
|
|
||||||
/// Handles all the linting of funky types
|
/// Handles all the linting of funky types
|
||||||
@ -74,17 +74,19 @@ impl LateLintPass for TypePass {
|
|||||||
if in_macro(cx, ast_ty.span) {
|
if in_macro(cx, ast_ty.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(did) = cx.tcx.def_map.borrow().get(&ast_ty.id) {
|
if let TyPath(ref qpath) = ast_ty.node {
|
||||||
if let def::Def::Struct(..) = did.full_def() {
|
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
|
||||||
if Some(did.full_def().def_id()) == cx.tcx.lang_items.owned_box() {
|
if let Some(def_id) = opt_def_id(def) {
|
||||||
|
if def_id == cx.tcx.lang_items.owned_box().unwrap() {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let TyPath(_, ref path) = ast_ty.node,
|
let QPath::Resolved(_, ref path) = *qpath,
|
||||||
let Some(ref last) = path.segments.last(),
|
let Some(ref last) = path.segments.last(),
|
||||||
let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
|
let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
|
||||||
let Some(ref vec) = ag.types.get(0),
|
let Some(ref vec) = ag.types.get(0),
|
||||||
let Some(did) = cx.tcx.def_map.borrow().get(&vec.id),
|
let TyPath(ref qpath) = vec.node,
|
||||||
let def::Def::Struct(..) = did.full_def(),
|
let def::Def::Struct(..) = cx.tcx.tables().qpath_def(qpath, vec.id),
|
||||||
match_def_path(cx, did.full_def().def_id(), &paths::VEC),
|
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,
|
span_help_and_lint(cx,
|
||||||
BOX_VEC,
|
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>`",
|
"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.");
|
"`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,
|
span_help_and_lint(cx,
|
||||||
LINKEDLIST,
|
LINKEDLIST,
|
||||||
ast_ty.span,
|
ast_ty.span,
|
||||||
"I see you're using a LinkedList! Perhaps you meant some other data structure?",
|
"I see you're using a LinkedList! Perhaps you meant some other data structure?",
|
||||||
"a VecDeque might work");
|
"a VecDeque might work");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use rustc::hir::*;
|
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::ast::Name;
|
use syntax::ast::*;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::symbol::InternedString;
|
use syntax::symbol::InternedString;
|
||||||
use utils::span_lint;
|
use utils::span_lint;
|
||||||
@ -34,16 +33,16 @@ impl LintPass for UnsafeNameRemoval {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for UnsafeNameRemoval {
|
impl EarlyLintPass for UnsafeNameRemoval {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
|
||||||
if let ItemUse(ref item_use) = item.node {
|
if let ItemKind::Use(ref item_use) = item.node {
|
||||||
match item_use.node {
|
match item_use.node {
|
||||||
ViewPath_::ViewPathSimple(ref name, ref path) => {
|
ViewPath_::ViewPathSimple(ref name, ref path) => {
|
||||||
unsafe_to_safe_check(
|
unsafe_to_safe_check(
|
||||||
path.segments
|
path.segments
|
||||||
.last()
|
.last()
|
||||||
.expect("use paths cannot be empty")
|
.expect("use paths cannot be empty")
|
||||||
.name,
|
.identifier,
|
||||||
*name,
|
*name,
|
||||||
cx, &item.span
|
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) {
|
fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: &Span) {
|
||||||
let old_str = old_name.as_str();
|
let old_str = old_name.name.as_str();
|
||||||
let new_str = new_name.as_str();
|
let new_str = new_name.name.as_str();
|
||||||
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
|
if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
UNSAFE_REMOVED_FROM_NAME,
|
UNSAFE_REMOVED_FROM_NAME,
|
||||||
|
@ -66,7 +66,7 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
|||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprBreak(Some(label), _) |
|
hir::ExprBreak(Some(label), _) |
|
||||||
hir::ExprAgain(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::ExprLoop(_, Some(label), _) |
|
||||||
hir::ExprWhile(_, _, Some(label)) => {
|
hir::ExprWhile(_, _, Some(label)) => {
|
||||||
|
@ -44,19 +44,6 @@ pub struct Range<'a> {
|
|||||||
|
|
||||||
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
|
/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
|
||||||
pub fn range(expr: &hir::Expr) -> Option<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.
|
/// 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> {
|
fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
|
||||||
let expr = &fields.iter()
|
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))
|
.unwrap_or_else(|| panic!("missing {} field for range", name))
|
||||||
.expr;
|
.expr;
|
||||||
|
|
||||||
Some(unwrap_unstable(expr))
|
Some(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The range syntax is expanded to literal paths starting with `core` or `std` depending on
|
// The range syntax is expanded to literal paths starting with `core` or `std` depending on
|
||||||
// `#[no_std]`. Testing both instead of resolving the paths.
|
// `#[no_std]`. Testing both instead of resolving the paths.
|
||||||
|
|
||||||
match unwrap_unstable(expr).node {
|
match expr.node {
|
||||||
hir::ExprPath(None, ref path) => {
|
hir::ExprPath(ref path) => {
|
||||||
if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
|
if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
|
||||||
Some(Range {
|
Some(Range {
|
||||||
start: None,
|
start: None,
|
||||||
@ -168,10 +155,10 @@ pub enum VecArgs<'a> {
|
|||||||
pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> {
|
pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> {
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let hir::ExprCall(ref fun, ref args) = expr.node,
|
let hir::ExprCall(ref fun, ref args) = expr.node,
|
||||||
let hir::ExprPath(_, ref path) = fun.node,
|
let hir::ExprPath(ref path) = fun.node,
|
||||||
let Some(fun_def) = resolve_node(cx, fun.id),
|
|
||||||
is_expn_of(cx, fun.span, "vec").is_some(),
|
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 {
|
return if match_def_path(cx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
|
||||||
// `vec![elem; size]` case
|
// `vec![elem; size]` case
|
||||||
Some(VecArgs::Repeat(&args[0], &args[1]))
|
Some(VecArgs::Repeat(&args[0], &args[1]))
|
||||||
|
@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
|||||||
|
|
||||||
match (&left.node, &right.node) {
|
match (&left.node, &right.node) {
|
||||||
(&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
|
(&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),
|
(&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)) => {
|
(&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)
|
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)) =>
|
(&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)),
|
&& both(le, re, |l, r| self.eq_expr(l, r)),
|
||||||
(&ExprBox(ref l), &ExprBox(ref 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)) => {
|
(&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),
|
(&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)),
|
(&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)) => {
|
(&ExprPath(ref l), &ExprPath(ref r)) => self.eq_qpath(l, r),
|
||||||
both(l_qself, r_qself, |l, r| self.eq_qself(l, r)) && self.eq_path(l_subpath, r_subpath)
|
|
||||||
}
|
|
||||||
(&ExprStruct(ref l_path, ref lf, ref lo), &ExprStruct(ref r_path, ref rf, ref ro)) => {
|
(&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))
|
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),
|
(&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) {
|
match (&left.node, &right.node) {
|
||||||
(&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
|
(&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)) => {
|
(&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)) => {
|
(&PatKind::Binding(ref lb, ref ld, ref li, ref lp), &PatKind::Binding(ref rb, ref rd, ref ri, ref rp)) => {
|
||||||
lb == rb && li.node.as_str() == ri.node.as_str() && both(lp, rp, |l, r| self.eq_pat(l, r))
|
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 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::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::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
|
||||||
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
|
(&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
|
||||||
ls == rs && over(l, r, |l, r| self.eq_pat(l, r))
|
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 {
|
fn eq_path(&self, left: &Path, right: &Path) -> bool {
|
||||||
left.global == right.global &&
|
left.global == right.global &&
|
||||||
over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
|
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)
|
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 {
|
fn eq_ty(&self, left: &Ty, right: &Ty) -> bool {
|
||||||
match (&left.node, &right.node) {
|
match (&left.node, &right.node) {
|
||||||
(&TySlice(ref l_vec), &TySlice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
|
(&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)) => {
|
(&TyRptr(_, ref l_rmut), &TyRptr(_, ref r_rmut)) => {
|
||||||
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
|
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)) => {
|
(&TyPath(ref l), &TyPath(ref r)) => self.eq_qpath(l, r),
|
||||||
both(lq, rq, |l, r| self.eq_qself(l, r)) && self.eq_path(l_path, r_path)
|
|
||||||
}
|
|
||||||
(&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
(&TyTup(ref l), &TyTup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)),
|
||||||
(&TyInfer, &TyInfer) => true,
|
(&TyInfer, &TyInfer) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -318,7 +320,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||||||
let c: fn(_) -> _ = ExprAgain;
|
let c: fn(_) -> _ = ExprAgain;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
if let Some(i) = i {
|
if let Some(i) = i {
|
||||||
self.hash_name(&i.node);
|
self.hash_name(&i.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprAssign(ref l, ref r) => {
|
ExprAssign(ref l, ref r) => {
|
||||||
@ -350,7 +352,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||||||
let c: fn(_, _) -> _ = ExprBreak;
|
let c: fn(_, _) -> _ = ExprBreak;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
if let Some(i) = i {
|
if let Some(i) = i {
|
||||||
self.hash_name(&i.node);
|
self.hash_name(&i.name);
|
||||||
}
|
}
|
||||||
if let Some(ref j) = *j {
|
if let Some(ref j) = *j {
|
||||||
self.hash_expr(&*j);
|
self.hash_expr(&*j);
|
||||||
@ -452,16 +454,16 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprPath(ref _qself, ref subpath) => {
|
ExprPath(ref qpath) => {
|
||||||
let c: fn(_, _) -> _ = ExprPath;
|
let c: fn(_) -> _ = ExprPath;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
self.hash_path(subpath);
|
self.hash_qpath(qpath);
|
||||||
}
|
}
|
||||||
ExprStruct(ref path, ref fields, ref expr) => {
|
ExprStruct(ref path, ref fields, ref expr) => {
|
||||||
let c: fn(_, _, _) -> _ = ExprStruct;
|
let c: fn(_, _, _) -> _ = ExprStruct;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
|
|
||||||
self.hash_path(path);
|
self.hash_qpath(path);
|
||||||
|
|
||||||
for f in fields {
|
for f in fields {
|
||||||
self.hash_name(&f.name.node);
|
self.hash_name(&f.name.node);
|
||||||
@ -526,6 +528,23 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||||||
n.as_str().hash(&mut self.s);
|
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) {
|
pub fn hash_path(&mut self, p: &Path) {
|
||||||
p.global.hash(&mut self.s);
|
p.global.hash(&mut self.s);
|
||||||
for p in &p.segments {
|
for p in &p.segments {
|
||||||
|
@ -275,11 +275,14 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
|
|||||||
println!("{}index expr:", ind);
|
println!("{}index expr:", ind);
|
||||||
print_expr(cx, idx, indent + 1);
|
print_expr(cx, idx, indent + 1);
|
||||||
},
|
},
|
||||||
hir::ExprPath(ref sel, ref path) => {
|
hir::ExprPath(hir::QPath::Resolved(ref ty, ref path)) => {
|
||||||
println!("{}Path, {}", ind, ty);
|
println!("{}Resolved Path, {:?}", ind, ty);
|
||||||
println!("{}self: {:?}", ind, sel);
|
|
||||||
println!("{}path: {:?}", ind, path);
|
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) => {
|
hir::ExprAddrOf(ref muta, ref e) => {
|
||||||
println!("{}AddrOf, {}", ind, ty);
|
println!("{}AddrOf, {}", ind, ty);
|
||||||
println!("mutability: {:?}", muta);
|
println!("mutability: {:?}", muta);
|
||||||
@ -354,7 +357,7 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
|
|||||||
println!("weird extern crate without a crate id");
|
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::ItemStatic(..) => println!("static item of type {:#?}", cx.tcx.item_type(did)),
|
||||||
hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.item_type(did)),
|
hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.item_type(did)),
|
||||||
hir::ItemFn(..) => {
|
hir::ItemFn(..) => {
|
||||||
@ -383,13 +386,11 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
|
|||||||
println!("trait has no default impl");
|
println!("trait has no default impl");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::ItemDefaultImpl(_, ref trait_ref) => {
|
hir::ItemDefaultImpl(_, ref _trait_ref) => {
|
||||||
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
|
println!("default impl");
|
||||||
println!("default impl for `{}`", cx.tcx.item_path_str(trait_did));
|
|
||||||
},
|
},
|
||||||
hir::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => {
|
hir::ItemImpl(_, _, _, Some(ref _trait_ref), _, _) => {
|
||||||
let trait_did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
|
println!("trait impl");
|
||||||
println!("impl of trait `{}`", cx.tcx.item_path_str(trait_did));
|
|
||||||
},
|
},
|
||||||
hir::ItemImpl(_, _, _, None, _, _) => {
|
hir::ItemImpl(_, _, _, None, _, _) => {
|
||||||
println!("impl");
|
println!("impl");
|
||||||
@ -402,7 +403,7 @@ fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
|
|||||||
println!("{}+", ind);
|
println!("{}+", ind);
|
||||||
match pat.node {
|
match pat.node {
|
||||||
hir::PatKind::Wild => println!("{}Wild", ind),
|
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!("{}Binding", ind);
|
||||||
println!("{}mode: {:?}", ind, mode);
|
println!("{}mode: {:?}", ind, mode);
|
||||||
println!("{}name: {}", ind, name.node);
|
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);
|
print_pat(cx, field, indent + 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hir::PatKind::Path(ref sel, ref path) => {
|
hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
|
||||||
println!("{}Path", ind);
|
println!("{}Resolved Path, {:?}", ind, ty);
|
||||||
println!("{}self: {:?}", ind, sel);
|
|
||||||
println!("{}path: {:?}", ind, path);
|
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) => {
|
hir::PatKind::Tuple(ref pats, opt_dots_position) => {
|
||||||
println!("{}Tuple", ind);
|
println!("{}Tuple", ind);
|
||||||
if let Some(dot_position) = opt_dots_position {
|
if let Some(dot_position) = opt_dots_position {
|
||||||
|
@ -140,7 +140,7 @@ impl LateLintPass for LintWithoutLintPass {
|
|||||||
|
|
||||||
fn is_lint_ref_type(ty: &Ty) -> bool {
|
fn is_lint_ref_type(ty: &Ty) -> bool {
|
||||||
if let TyRptr(Some(_), MutTy { ty: ref inner, mutbl: MutImmutable }) = ty.node {
|
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);
|
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 {
|
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)
|
match_path(path, &paths::LINT_ARRAY)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||||
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::map::Node;
|
use rustc::hir::map::Node;
|
||||||
use rustc::lint::{LintContext, LateContext, Level, Lint};
|
use rustc::lint::{LintContext, LateContext, Level, Lint};
|
||||||
use rustc::session::Session;
|
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"])
|
/// 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)
|
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`.
|
/// Resolve the definition of a node from its `NodeId`.
|
||||||
pub fn resolve_node(cx: &LateContext, id: NodeId) -> Option<def::Def> {
|
pub fn resolve_node(cx: &LateContext, qpath: &QPath, id: NodeId) -> def::Def {
|
||||||
cx.tcx.def_map.borrow().get(&id).map(|d| d.full_def())
|
cx.tcx.tables().qpath_def(qpath, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Match an `Expr` against a chain of methods, and return the matched `Expr`s.
|
/// 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.
|
/// Return whether a pattern is refutable.
|
||||||
pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool {
|
pub fn is_refutable(cx: &LateContext, pat: &Pat) -> bool {
|
||||||
fn is_enum_variant(cx: &LateContext, did: NodeId) -> bool {
|
fn is_enum_variant(cx: &LateContext, qpath: &QPath, did: NodeId) -> bool {
|
||||||
matches!(cx.tcx.def_map.borrow().get(&did).map(|d| d.full_def()), Some(def::Def::Variant(..)) | Some(def::Def::VariantCtor(..)))
|
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 {
|
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::Binding(..) | PatKind::Wild => false,
|
||||||
PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
|
PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
|
||||||
PatKind::Lit(..) | PatKind::Range(..) => true,
|
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::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
|
||||||
PatKind::Struct(_, ref fields, _) => {
|
PatKind::Struct(ref qpath, ref fields, _) => {
|
||||||
if is_enum_variant(cx, pat.id) {
|
if is_enum_variant(cx, qpath, pat.id) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
are_refutable(cx, fields.iter().map(|field| &*field.node.pat))
|
are_refutable(cx, fields.iter().map(|field| &*field.node.pat))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::TupleStruct(_, ref pats, _) => {
|
PatKind::TupleStruct(ref qpath, ref pats, _) => {
|
||||||
if is_enum_variant(cx, pat.id) {
|
if is_enum_variant(cx, qpath, pat.id) {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
are_refutable(cx, pats.iter().map(|pat| &**pat))
|
are_refutable(cx, pats.iter().map(|pat| &**pat))
|
||||||
@ -793,3 +802,20 @@ pub fn remove_blocks(expr: &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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user