enum glob use and copies left
This commit is contained in:
@@ -48,6 +48,8 @@ impl EnumGlobUse {
|
|||||||
return; // re-exports are fine
|
return; // re-exports are fine
|
||||||
}
|
}
|
||||||
if let ItemUse(ref path, UseKind::Glob) = item.node {
|
if let ItemUse(ref path, UseKind::Glob) = item.node {
|
||||||
|
// FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;`
|
||||||
|
// extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an `Enum`
|
||||||
if let Def::Enum(_) = path.def {
|
if let Def::Enum(_) = path.def {
|
||||||
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
|
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use rustc::hir::*;
|
|||||||
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
|
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{in_external_macro, span_lint};
|
use utils::{in_external_macro, span_lint, last_path_segment};
|
||||||
|
|
||||||
/// **What it does:** Checks for lifetime annotations which can be removed by
|
/// **What it does:** Checks for lifetime annotations which can be removed by
|
||||||
/// relying on lifetime elision.
|
/// relying on lifetime elision.
|
||||||
@@ -240,26 +240,24 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
|
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
|
||||||
if let QPath::Resolved(_, ref path) = *qpath {
|
let last_path_segment = &last_path_segment(qpath).parameters;
|
||||||
let last_path_segment = path.segments.last().map(|s| &s.parameters);
|
if let &AngleBracketedParameters(ref params) = last_path_segment {
|
||||||
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
|
if params.lifetimes.is_empty() {
|
||||||
if params.lifetimes.is_empty() {
|
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
|
||||||
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);
|
for _ in generics.regions.as_slice() {
|
||||||
for _ in generics.regions.as_slice() {
|
self.record(&None);
|
||||||
self.record(&None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Def::Trait(def_id) => {
|
|
||||||
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
|
|
||||||
for _ in &trait_def.generics.regions {
|
|
||||||
self.record(&None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
Def::Trait(def_id) => {
|
||||||
|
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
|
||||||
|
for _ in &trait_def.generics.regions {
|
||||||
|
self.record(&None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use utils::sugg;
|
|||||||
|
|
||||||
use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg,
|
use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg,
|
||||||
in_external_macro, is_refutable, span_help_and_lint, is_integer_literal,
|
in_external_macro, is_refutable, span_help_and_lint, is_integer_literal,
|
||||||
get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty};
|
get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty, last_path_segment};
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
|
|
||||||
/// **What it does:** Checks for looping over the range of `0..len` of some
|
/// **What it does:** Checks for looping over the range of `0..len` of some
|
||||||
@@ -369,26 +369,23 @@ impl LateLintPass for Pass {
|
|||||||
if let (&PatKind::TupleStruct(ref qpath, 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 QPath::Resolved(_, ref path) = *qpath {
|
let lhs_constructor = last_path_segment(qpath);
|
||||||
if let Some(lhs_constructor) = path.segments.last() {
|
if &*method_name.node.as_str() == "next" &&
|
||||||
if &*method_name.node.as_str() == "next" &&
|
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
|
||||||
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
|
&*lhs_constructor.name.as_str() == "Some" &&
|
||||||
&*lhs_constructor.name.as_str() == "Some" &&
|
!is_refutable(cx, &pat_args[0]) &&
|
||||||
!is_refutable(cx, &pat_args[0]) &&
|
!is_iterator_used_after_while_let(cx, iter_expr) {
|
||||||
!is_iterator_used_after_while_let(cx, iter_expr) {
|
let iterator = snippet(cx, method_args[0].span, "_");
|
||||||
let iterator = snippet(cx, method_args[0].span, "_");
|
let loop_var = snippet(cx, pat_args[0].span, "_");
|
||||||
let loop_var = snippet(cx, pat_args[0].span, "_");
|
span_lint_and_then(cx,
|
||||||
span_lint_and_then(cx,
|
WHILE_LET_ON_ITERATOR,
|
||||||
WHILE_LET_ON_ITERATOR,
|
expr.span,
|
||||||
expr.span,
|
"this loop could be written as a `for` loop",
|
||||||
"this loop could be written as a `for` loop",
|
|db| {
|
||||||
|db| {
|
db.span_suggestion(expr.span,
|
||||||
db.span_suggestion(expr.span,
|
"try",
|
||||||
"try",
|
format!("for {} in {} {{ .. }}", loop_var, iterator));
|
||||||
format!("for {} in {} {{ .. }}", loop_var, iterator));
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use rustc::lint::*;
|
|||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::middle::const_qualif::ConstQualif;
|
use rustc::middle::const_qualif::ConstQualif;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
|
use rustc::hir::def::Def;
|
||||||
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
use rustc_const_eval::EvalHint::ExprTypeChecked;
|
||||||
use rustc_const_eval::eval_const_expr_partial;
|
use rustc_const_eval::eval_const_expr_partial;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@@ -10,7 +11,8 @@ use std::fmt;
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path,
|
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path,
|
||||||
match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet,
|
match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet,
|
||||||
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
|
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth,
|
||||||
|
last_path_segment, single_segment_path, match_def_path};
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
use utils::sugg;
|
use utils::sugg;
|
||||||
|
|
||||||
@@ -701,12 +703,8 @@ 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(hir::QPath::Resolved(_, ref path)) = fun.node {
|
if let hir::ExprPath(ref qpath) = fun.node {
|
||||||
let path: &str = &path.segments
|
let path: &str = &*last_path_segment(qpath).name.as_str();
|
||||||
.last()
|
|
||||||
.expect("A path must have at least one segment")
|
|
||||||
.name
|
|
||||||
.as_str();
|
|
||||||
|
|
||||||
if ["default", "new"].contains(&path) {
|
if ["default", "new"].contains(&path) {
|
||||||
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
let arg_ty = cx.tcx.tables().expr_ty(arg);
|
||||||
@@ -878,7 +876,8 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
|
|||||||
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(ref path) = fun.node,
|
let hir::ExprPath(ref path) = fun.node,
|
||||||
match_path(path, &paths::CSTRING_NEW),
|
let Def::Method(did) = cx.tcx.tables().qpath_def(path, fun.id),
|
||||||
|
match_def_path(cx, did, &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,
|
||||||
"you are getting the inner pointer of a temporary `CString`",
|
"you are getting the inner pointer of a temporary `CString`",
|
||||||
@@ -1188,8 +1187,9 @@ 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(hir::QPath::Resolved(None, ref path)) = fun.node,
|
let hir::ExprPath(ref qpath) = fun.node,
|
||||||
path.segments.len() == 1 && &*path.segments[0].name.as_str() == "Some"
|
let Some(segment) = single_segment_path(qpath),
|
||||||
|
&*segment.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]));
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use rustc_const_math::ConstFloat;
|
|||||||
use syntax::codemap::{Span, Spanned, ExpnFormat};
|
use syntax::codemap::{Span, Spanned, ExpnFormat};
|
||||||
use utils::{
|
use utils::{
|
||||||
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
|
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
|
||||||
snippet, span_lint, span_lint_and_then, walk_ptrs_ty
|
snippet, span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment
|
||||||
};
|
};
|
||||||
use utils::sugg::Sugg;
|
use utils::sugg::Sugg;
|
||||||
|
|
||||||
@@ -263,22 +263,14 @@ impl LateLintPass for Pass {
|
|||||||
}
|
}
|
||||||
let binding = match expr.node {
|
let binding = match expr.node {
|
||||||
ExprPath(ref qpath) => {
|
ExprPath(ref qpath) => {
|
||||||
if let QPath::Resolved(_, ref path) = *qpath {
|
let binding = last_path_segment(qpath).name.as_str();
|
||||||
let binding = path.segments
|
if binding.starts_with('_') &&
|
||||||
.last()
|
!binding.starts_with("__") &&
|
||||||
.expect("path should always have at least one segment")
|
&*binding != "_result" && // FIXME: #944
|
||||||
.name
|
is_used(cx, expr) &&
|
||||||
.as_str();
|
// don't lint if the declaration is in a macro
|
||||||
if binding.starts_with('_') &&
|
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
|
||||||
!binding.starts_with("__") &&
|
Some(binding)
|
||||||
&*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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,17 +75,13 @@ impl LateLintPass for StepByZero {
|
|||||||
// .iter() and .len() called on same Path
|
// .iter() and .len() called on same Path
|
||||||
let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_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,
|
let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node,
|
||||||
iter_path == len_path
|
iter_path.segments == len_path.segments
|
||||||
], {
|
], {
|
||||||
let Path { segments: ref iter_path, .. } = **iter_path;
|
span_lint(cx,
|
||||||
let Path { segments: ref len_path, .. } = **len_path;
|
RANGE_ZIP_WITH_LEN,
|
||||||
if iter_path == len_path {
|
expr.span,
|
||||||
span_lint(cx,
|
&format!("It is more idiomatic to use {}.iter().enumerate()",
|
||||||
RANGE_ZIP_WITH_LEN,
|
snippet(cx, iter_args[0].span, "_")));
|
||||||
expr.span,
|
|
||||||
&format!("It is more idiomatic to use {}.iter().enumerate()",
|
|
||||||
snippet(cx, iter_args[0].span, "_")));
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use rustc::lint::*;
|
|||||||
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
|
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet};
|
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment};
|
||||||
use utils::sugg;
|
use utils::sugg;
|
||||||
|
|
||||||
/// **What it does:** Checks for transmutes that can't ever be correct on any
|
/// **What it does:** Checks for transmutes that can't ever be correct on any
|
||||||
@@ -191,9 +191,8 @@ impl LateLintPass for Transmute {
|
|||||||
/// 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: &QPath, to_rty: ty::Ty) -> String {
|
fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: ty::Ty) -> String {
|
||||||
|
let seg = last_path_segment(path);
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let QPath::Resolved(_, ref path) = *path,
|
|
||||||
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),
|
||||||
let TyRptr(_, ref to_ty) = to_ty.node,
|
let TyRptr(_, ref to_ty) = to_ty.node,
|
||||||
|
|||||||
@@ -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, opt_def_id};
|
span_help_and_lint, span_lint, opt_def_id, last_path_segment};
|
||||||
use utils::paths;
|
use utils::paths;
|
||||||
|
|
||||||
/// Handles all the linting of funky types
|
/// Handles all the linting of funky types
|
||||||
@@ -78,9 +78,8 @@ impl LateLintPass for TypePass {
|
|||||||
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
|
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
|
||||||
if let Some(def_id) = opt_def_id(def) {
|
if let Some(def_id) = opt_def_id(def) {
|
||||||
if def_id == cx.tcx.lang_items.owned_box().unwrap() {
|
if def_id == cx.tcx.lang_items.owned_box().unwrap() {
|
||||||
|
let last = last_path_segment(qpath);
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let QPath::Resolved(_, ref path) = *qpath,
|
|
||||||
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 TyPath(ref qpath) = vec.node,
|
let TyPath(ref qpath) = vec.node,
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e
|
|||||||
// `vec![elem; size]` case
|
// `vec![elem; size]` case
|
||||||
Some(VecArgs::Repeat(&args[0], &args[1]))
|
Some(VecArgs::Repeat(&args[0], &args[1]))
|
||||||
}
|
}
|
||||||
else if match_path(path, &["into_vec"]) && args.len() == 1 {
|
else if match_def_path(cx, fun_def.def_id(), &paths::SLICE_INTO_VEC) && args.len() == 1 {
|
||||||
// `vec![a, b, c]` case
|
// `vec![a, b, c]` case
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let hir::ExprBox(ref boxed) = args[0].node,
|
let hir::ExprBox(ref boxed) = args[0].node,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use rustc::lint::*;
|
|||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use syntax::ast::Name;
|
use syntax::ast::{Name, NodeId};
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use utils::differing_macro_contexts;
|
use utils::differing_macro_contexts;
|
||||||
|
|
||||||
@@ -457,13 +457,13 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
|||||||
ExprPath(ref qpath) => {
|
ExprPath(ref qpath) => {
|
||||||
let c: fn(_) -> _ = ExprPath;
|
let c: fn(_) -> _ = ExprPath;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
self.hash_qpath(qpath);
|
self.hash_qpath(qpath, e.id);
|
||||||
}
|
}
|
||||||
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_qpath(path);
|
self.hash_qpath(path, e.id);
|
||||||
|
|
||||||
for f in fields {
|
for f in fields {
|
||||||
self.hash_name(&f.name.node);
|
self.hash_name(&f.name.node);
|
||||||
@@ -528,21 +528,8 @@ 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) {
|
pub fn hash_qpath(&mut self, p: &QPath, id: NodeId) {
|
||||||
match *p {
|
self.cx.tcx.tables().qpath_def(p, id).hash(&mut self.s);
|
||||||
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) {
|
||||||
|
|||||||
@@ -95,7 +95,16 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
|
|||||||
}
|
}
|
||||||
/// Returns true if this `expn_info` was expanded by any macro.
|
/// Returns true if this `expn_info` was expanded by any macro.
|
||||||
pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool {
|
pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool {
|
||||||
cx.sess().codemap().with_expn_info(span.expn_id, |info| info.is_some())
|
cx.sess().codemap().with_expn_info(span.expn_id, |info| match info {
|
||||||
|
Some(info) => {
|
||||||
|
match info.callee.format {
|
||||||
|
// don't treat range expressions desugared to structs as "in_macro"
|
||||||
|
ExpnFormat::CompilerDesugaring(name) => name != "...",
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => false,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the macro that expanded the crate was outside of the current crate or was a
|
/// Returns true if the macro that expanded the crate was outside of the current crate or was a
|
||||||
@@ -150,6 +159,9 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool {
|
|||||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||||
|
|
||||||
cx.tcx.push_item_path(&mut apb, def_id);
|
cx.tcx.push_item_path(&mut apb, def_id);
|
||||||
|
if path == paths::VEC_FROM_ELEM {
|
||||||
|
println!("{:#?} == {:#?}", apb.names, path);
|
||||||
|
}
|
||||||
|
|
||||||
apb.names.len() == path.len() &&
|
apb.names.len() == path.len() &&
|
||||||
apb.names.iter().zip(path.iter()).all(|(a, &b)| &**a == b)
|
apb.names.iter().zip(path.iter()).all(|(a, &b)| &**a == b)
|
||||||
@@ -197,6 +209,23 @@ pub fn match_trait_method(cx: &LateContext, expr: &Expr, path: &[&str]) -> bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn last_path_segment(path: &QPath) -> &PathSegment {
|
||||||
|
match *path {
|
||||||
|
QPath::Resolved(_, ref path) => path.segments
|
||||||
|
.last()
|
||||||
|
.expect("A path must have at least one segment"),
|
||||||
|
QPath::TypeRelative(_, ref seg) => &seg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn single_segment_path(path: &QPath) -> Option<&PathSegment> {
|
||||||
|
match *path {
|
||||||
|
QPath::Resolved(_, ref path) if path.segments.len() == 1 => Some(&path.segments[0]),
|
||||||
|
QPath::Resolved(..) => None,
|
||||||
|
QPath::TypeRelative(_, ref seg) => Some(&seg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Match a `Path` against a slice of segment string literals.
|
/// Match a `Path` against a slice of segment string literals.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@@ -204,10 +233,16 @@ 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: &QPath, segments: &[&str]) -> bool {
|
pub fn match_path(path: &QPath, segments: &[&str]) -> bool {
|
||||||
if let QPath::Resolved(_, ref path) = *path {
|
match *path {
|
||||||
match_path_old(path, segments)
|
QPath::Resolved(_, ref path) => match_path_old(path, segments),
|
||||||
} else {
|
QPath::TypeRelative(ref ty, ref segment) => match ty.node {
|
||||||
false
|
TyPath(ref inner_path) => {
|
||||||
|
segments.len() > 0 &&
|
||||||
|
match_path(inner_path, &segments[..(segments.len() - 1)]) &&
|
||||||
|
segment.name == segments[segments.len() - 1]
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub const CLONE_TRAIT: [&'static str; 3] = ["core", "clone", "Clone"];
|
|||||||
pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"];
|
pub const CMP_MAX: [&'static str; 3] = ["core", "cmp", "max"];
|
||||||
pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"];
|
pub const CMP_MIN: [&'static str; 3] = ["core", "cmp", "min"];
|
||||||
pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"];
|
pub const COW: [&'static str; 3] = ["collections", "borrow", "Cow"];
|
||||||
pub const CSTRING_NEW: [&'static str; 4] = ["std", "ffi", "CString", "new"];
|
pub const CSTRING_NEW: [&'static str; 5] = ["std", "ffi", "c_str", "CString", "new"];
|
||||||
pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"];
|
pub const DEBUG_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Debug", "fmt"];
|
||||||
pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"];
|
pub const DEFAULT_TRAIT: [&'static str; 3] = ["core", "default", "Default"];
|
||||||
pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"];
|
pub const DISPLAY_FMT_METHOD: [&'static str; 4] = ["core", "fmt", "Display", "fmt"];
|
||||||
@@ -64,6 +64,7 @@ pub const RESULT: [&'static str; 3] = ["core", "result", "Result"];
|
|||||||
pub const RESULT_ERR: [&'static str; 4] = ["core", "result", "Result", "Err"];
|
pub const RESULT_ERR: [&'static str; 4] = ["core", "result", "Result", "Err"];
|
||||||
pub const RESULT_OK: [&'static str; 4] = ["core", "result", "Result", "Ok"];
|
pub const RESULT_OK: [&'static str; 4] = ["core", "result", "Result", "Ok"];
|
||||||
pub const SERDE_DE_VISITOR: [&'static str; 3] = ["serde", "de", "Visitor"];
|
pub const SERDE_DE_VISITOR: [&'static str; 3] = ["serde", "de", "Visitor"];
|
||||||
|
pub const SLICE_INTO_VEC: [&'static str; 4] = ["collections", "slice", "<impl [T]>", "into_vec"];
|
||||||
pub const STRING: [&'static str; 3] = ["collections", "string", "String"];
|
pub const STRING: [&'static str; 3] = ["collections", "string", "String"];
|
||||||
pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"];
|
pub const TRANSMUTE: [&'static str; 4] = ["core", "intrinsics", "", "transmute"];
|
||||||
pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"];
|
pub const VEC: [&'static str; 3] = ["collections", "vec", "Vec"];
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#![allow(blacklisted_name)]
|
#![allow(blacklisted_name)]
|
||||||
#![allow(collapsible_if)]
|
#![allow(collapsible_if)]
|
||||||
#![allow(zero_divided_by_zero, eq_op)]
|
#![allow(zero_divided_by_zero, eq_op)]
|
||||||
|
#![allow(path_statements)]
|
||||||
|
|
||||||
fn bar<T>(_: T) {}
|
fn bar<T>(_: T) {}
|
||||||
fn foo() -> bool { unimplemented!() }
|
fn foo() -> bool { unimplemented!() }
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ pub fn test(_: LinkedList<u8>) { //~ ERROR I see you're using a LinkedList!
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main(){
|
fn main(){
|
||||||
test(LinkedList::new());
|
test(LinkedList::new()); //~ ERROR I see you're using a LinkedList!
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ fn run_mode(dir: &'static str, mode: &'static str) {
|
|||||||
|
|
||||||
fn prepare_env() {
|
fn prepare_env() {
|
||||||
set_var("CLIPPY_DISABLE_WIKI_LINKS", "true");
|
set_var("CLIPPY_DISABLE_WIKI_LINKS", "true");
|
||||||
|
set_var("RUST_BACKTRACE", "0"); // these are riddicously slow right now
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user