Skip to content

Commit 16aab71

Browse files
committed
enum glob use and copies left
1 parent 59b0077 commit 16aab71

File tree

15 files changed

+116
-108
lines changed

15 files changed

+116
-108
lines changed

clippy_lints/src/enum_glob_use.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ impl EnumGlobUse {
4848
return; // re-exports are fine
4949
}
5050
if let ItemUse(ref path, UseKind::Glob) = item.node {
51+
// FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;`
52+
// extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an `Enum`
5153
if let Def::Enum(_) = path.def {
5254
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
5355
}

clippy_lints/src/lifetimes.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc::hir::*;
55
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
66
use std::collections::{HashSet, HashMap};
77
use syntax::codemap::Span;
8-
use utils::{in_external_macro, span_lint};
8+
use utils::{in_external_macro, span_lint, last_path_segment};
99

1010
/// **What it does:** Checks for lifetime annotations which can be removed by
1111
/// relying on lifetime elision.
@@ -240,26 +240,24 @@ impl<'v, 't> RefVisitor<'v, 't> {
240240
}
241241

242242
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
243-
if let QPath::Resolved(_, ref path) = *qpath {
244-
let last_path_segment = path.segments.last().map(|s| &s.parameters);
245-
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
246-
if params.lifetimes.is_empty() {
247-
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
248-
Def::TyAlias(def_id) |
249-
Def::Struct(def_id) => {
250-
let generics = self.cx.tcx.item_generics(def_id);
251-
for _ in generics.regions.as_slice() {
252-
self.record(&None);
253-
}
243+
let last_path_segment = &last_path_segment(qpath).parameters;
244+
if let &AngleBracketedParameters(ref params) = last_path_segment {
245+
if params.lifetimes.is_empty() {
246+
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
247+
Def::TyAlias(def_id) |
248+
Def::Struct(def_id) => {
249+
let generics = self.cx.tcx.item_generics(def_id);
250+
for _ in generics.regions.as_slice() {
251+
self.record(&None);
254252
}
255-
Def::Trait(def_id) => {
256-
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
257-
for _ in &trait_def.generics.regions {
258-
self.record(&None);
259-
}
253+
}
254+
Def::Trait(def_id) => {
255+
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
256+
for _ in &trait_def.generics.regions {
257+
self.record(&None);
260258
}
261-
_ => (),
262259
}
260+
_ => (),
263261
}
264262
}
265263
}

clippy_lints/src/loops.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use utils::sugg;
1616

1717
use utils::{snippet, span_lint, get_parent_expr, match_trait_method, match_type, multispan_sugg,
1818
in_external_macro, is_refutable, span_help_and_lint, is_integer_literal,
19-
get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty};
19+
get_enclosing_block, span_lint_and_then, higher, walk_ptrs_ty, last_path_segment};
2020
use utils::paths;
2121

2222
/// **What it does:** Checks for looping over the range of `0..len` of some
@@ -369,26 +369,23 @@ impl LateLintPass for Pass {
369369
if let (&PatKind::TupleStruct(ref qpath, ref pat_args, _),
370370
&ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) {
371371
let iter_expr = &method_args[0];
372-
if let QPath::Resolved(_, ref path) = *qpath {
373-
if let Some(lhs_constructor) = path.segments.last() {
374-
if &*method_name.node.as_str() == "next" &&
375-
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
376-
&*lhs_constructor.name.as_str() == "Some" &&
377-
!is_refutable(cx, &pat_args[0]) &&
378-
!is_iterator_used_after_while_let(cx, iter_expr) {
379-
let iterator = snippet(cx, method_args[0].span, "_");
380-
let loop_var = snippet(cx, pat_args[0].span, "_");
381-
span_lint_and_then(cx,
382-
WHILE_LET_ON_ITERATOR,
383-
expr.span,
384-
"this loop could be written as a `for` loop",
385-
|db| {
386-
db.span_suggestion(expr.span,
387-
"try",
388-
format!("for {} in {} {{ .. }}", loop_var, iterator));
389-
});
390-
}
391-
}
372+
let lhs_constructor = last_path_segment(qpath);
373+
if &*method_name.node.as_str() == "next" &&
374+
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
375+
&*lhs_constructor.name.as_str() == "Some" &&
376+
!is_refutable(cx, &pat_args[0]) &&
377+
!is_iterator_used_after_while_let(cx, iter_expr) {
378+
let iterator = snippet(cx, method_args[0].span, "_");
379+
let loop_var = snippet(cx, pat_args[0].span, "_");
380+
span_lint_and_then(cx,
381+
WHILE_LET_ON_ITERATOR,
382+
expr.span,
383+
"this loop could be written as a `for` loop",
384+
|db| {
385+
db.span_suggestion(expr.span,
386+
"try",
387+
format!("for {} in {} {{ .. }}", loop_var, iterator));
388+
});
392389
}
393390
}
394391
}

clippy_lints/src/methods.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ use rustc::lint::*;
33
use rustc::middle::const_val::ConstVal;
44
use rustc::middle::const_qualif::ConstQualif;
55
use rustc::ty;
6+
use rustc::hir::def::Def;
67
use rustc_const_eval::EvalHint::ExprTypeChecked;
78
use rustc_const_eval::eval_const_expr_partial;
89
use std::borrow::Cow;
910
use std::fmt;
1011
use syntax::codemap::Span;
1112
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path,
1213
match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet,
13-
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
14+
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth,
15+
last_path_segment, single_segment_path, match_def_path};
1416
use utils::paths;
1517
use utils::sugg;
1618

@@ -701,12 +703,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
701703
}
702704

703705
if name == "unwrap_or" {
704-
if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = fun.node {
705-
let path: &str = &path.segments
706-
.last()
707-
.expect("A path must have at least one segment")
708-
.name
709-
.as_str();
706+
if let hir::ExprPath(ref qpath) = fun.node {
707+
let path: &str = &*last_path_segment(qpath).name.as_str();
710708

711709
if ["default", "new"].contains(&path) {
712710
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
878876
let hir::ExprCall(ref fun, ref args) = new.node,
879877
args.len() == 1,
880878
let hir::ExprPath(ref path) = fun.node,
881-
match_path(path, &paths::CSTRING_NEW),
879+
let Def::Method(did) = cx.tcx.tables().qpath_def(path, fun.id),
880+
match_def_path(cx, did, &paths::CSTRING_NEW)
882881
], {
883882
span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span,
884883
"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:
11881187
let Some(args) = method_chain_args(chain, &["chars", "next"]),
11891188
let hir::ExprCall(ref fun, ref arg_char) = other.node,
11901189
arg_char.len() == 1,
1191-
let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = fun.node,
1192-
path.segments.len() == 1 && &*path.segments[0].name.as_str() == "Some"
1190+
let hir::ExprPath(ref qpath) = fun.node,
1191+
let Some(segment) = single_segment_path(qpath),
1192+
&*segment.name.as_str() == "Some"
11931193
], {
11941194
let self_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty_adjusted(&args[0][0]));
11951195

clippy_lints/src/misc.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_const_math::ConstFloat;
1010
use syntax::codemap::{Span, Spanned, ExpnFormat};
1111
use utils::{
1212
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
13-
snippet, span_lint, span_lint_and_then, walk_ptrs_ty
13+
snippet, span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment
1414
};
1515
use utils::sugg::Sugg;
1616

@@ -263,22 +263,14 @@ impl LateLintPass for Pass {
263263
}
264264
let binding = match expr.node {
265265
ExprPath(ref qpath) => {
266-
if let QPath::Resolved(_, ref path) = *qpath {
267-
let binding = path.segments
268-
.last()
269-
.expect("path should always have at least one segment")
270-
.name
271-
.as_str();
272-
if binding.starts_with('_') &&
273-
!binding.starts_with("__") &&
274-
&*binding != "_result" && // FIXME: #944
275-
is_used(cx, expr) &&
276-
// don't lint if the declaration is in a macro
277-
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
278-
Some(binding)
279-
} else {
280-
None
281-
}
266+
let binding = last_path_segment(qpath).name.as_str();
267+
if binding.starts_with('_') &&
268+
!binding.starts_with("__") &&
269+
&*binding != "_result" && // FIXME: #944
270+
is_used(cx, expr) &&
271+
// don't lint if the declaration is in a macro
272+
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
273+
Some(binding)
282274
} else {
283275
None
284276
}

clippy_lints/src/ranges.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,13 @@ impl LateLintPass for StepByZero {
7575
// .iter() and .len() called on same Path
7676
let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node,
7777
let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node,
78-
iter_path == len_path
78+
iter_path.segments == len_path.segments
7979
], {
80-
let Path { segments: ref iter_path, .. } = **iter_path;
81-
let Path { segments: ref len_path, .. } = **len_path;
82-
if iter_path == len_path {
83-
span_lint(cx,
84-
RANGE_ZIP_WITH_LEN,
85-
expr.span,
86-
&format!("It is more idiomatic to use {}.iter().enumerate()",
87-
snippet(cx, iter_args[0].span, "_")));
88-
}
80+
span_lint(cx,
81+
RANGE_ZIP_WITH_LEN,
82+
expr.span,
83+
&format!("It is more idiomatic to use {}.iter().enumerate()",
84+
snippet(cx, iter_args[0].span, "_")));
8985
}}
9086
}
9187
}

clippy_lints/src/transmute.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc::lint::*;
22
use rustc::ty::TypeVariants::{TyRawPtr, TyRef};
33
use rustc::ty;
44
use rustc::hir::*;
5-
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet};
5+
use utils::{match_def_path, paths, span_lint, span_lint_and_then, snippet, last_path_segment};
66
use utils::sugg;
77

88
/// **What it does:** Checks for transmutes that can't ever be correct on any
@@ -191,9 +191,8 @@ impl LateLintPass for Transmute {
191191
/// the type's `ToString` implementation. In weird cases it could lead to types with invalid `'_`
192192
/// lifetime, but it should be rare.
193193
fn get_type_snippet(cx: &LateContext, path: &QPath, to_rty: ty::Ty) -> String {
194+
let seg = last_path_segment(path);
194195
if_let_chain!{[
195-
let QPath::Resolved(_, ref path) = *path,
196-
let Some(seg) = path.segments.last(),
197196
let PathParameters::AngleBracketedParameters(ref ang) = seg.parameters,
198197
let Some(to_ty) = ang.types.get(1),
199198
let TyRptr(_, ref to_ty) = to_ty.node,

clippy_lints/src/types.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::cmp::Ordering;
77
use syntax::ast::{IntTy, UintTy, FloatTy};
88
use syntax::codemap::Span;
99
use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet,
10-
span_help_and_lint, span_lint, opt_def_id};
10+
span_help_and_lint, span_lint, opt_def_id, last_path_segment};
1111
use utils::paths;
1212

1313
/// Handles all the linting of funky types
@@ -78,9 +78,8 @@ impl LateLintPass for TypePass {
7878
let def = cx.tcx.tables().qpath_def(qpath, ast_ty.id);
7979
if let Some(def_id) = opt_def_id(def) {
8080
if def_id == cx.tcx.lang_items.owned_box().unwrap() {
81+
let last = last_path_segment(qpath);
8182
if_let_chain! {[
82-
let QPath::Resolved(_, ref path) = *qpath,
83-
let Some(ref last) = path.segments.last(),
8483
let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
8584
let Some(ref vec) = ag.types.get(0),
8685
let TyPath(ref qpath) = vec.node,

clippy_lints/src/utils/higher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e
163163
// `vec![elem; size]` case
164164
Some(VecArgs::Repeat(&args[0], &args[1]))
165165
}
166-
else if match_path(path, &["into_vec"]) && args.len() == 1 {
166+
else if match_def_path(cx, fun_def.def_id(), &paths::SLICE_INTO_VEC) && args.len() == 1 {
167167
// `vec![a, b, c]` case
168168
if_let_chain!{[
169169
let hir::ExprBox(ref boxed) = args[0].node,

clippy_lints/src/utils/hir.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc::lint::*;
33
use rustc::hir::*;
44
use std::hash::{Hash, Hasher};
55
use std::collections::hash_map::DefaultHasher;
6-
use syntax::ast::Name;
6+
use syntax::ast::{Name, NodeId};
77
use syntax::ptr::P;
88
use utils::differing_macro_contexts;
99

@@ -457,13 +457,13 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
457457
ExprPath(ref qpath) => {
458458
let c: fn(_) -> _ = ExprPath;
459459
c.hash(&mut self.s);
460-
self.hash_qpath(qpath);
460+
self.hash_qpath(qpath, e.id);
461461
}
462462
ExprStruct(ref path, ref fields, ref expr) => {
463463
let c: fn(_, _, _) -> _ = ExprStruct;
464464
c.hash(&mut self.s);
465465

466-
self.hash_qpath(path);
466+
self.hash_qpath(path, e.id);
467467

468468
for f in fields {
469469
self.hash_name(&f.name.node);
@@ -528,21 +528,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
528528
n.as_str().hash(&mut self.s);
529529
}
530530

531-
pub fn hash_qpath(&mut self, p: &QPath) {
532-
match *p {
533-
QPath::Resolved(ref _ty, ref path) => {
534-
let c: fn(_, _) -> _ = QPath::Resolved;
535-
c.hash(&mut self.s);
536-
// self.hash_ty(ty); FIXME
537-
self.hash_path(path);
538-
},
539-
QPath::TypeRelative(ref _ty, ref seg) => {
540-
let c: fn(_, _) -> _ = QPath::TypeRelative;
541-
c.hash(&mut self.s);
542-
// self.hash_ty(ty); FIXME
543-
self.hash_name(&seg.name);
544-
},
545-
}
531+
pub fn hash_qpath(&mut self, p: &QPath, id: NodeId) {
532+
self.cx.tcx.tables().qpath_def(p, id).hash(&mut self.s);
546533
}
547534

548535
pub fn hash_path(&mut self, p: &Path) {

0 commit comments

Comments
 (0)