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