Skip to content

Commit 2a45a2a

Browse files
committed
Use utils::sugg in FOR_KV_MAP
1 parent f6c9490 commit 2a45a2a

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

clippy_lints/src/loops.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -596,33 +596,34 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex
596596

597597
/// Check for the `FOR_KV_MAP` lint.
598598
fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
599+
let pat_span = pat.span;
600+
599601
if let PatKind::Tuple(ref pat, _) = pat.node {
600602
if pat.len() == 2 {
601-
let (pat_span, kind) = match (&pat[0].node, &pat[1].node) {
602-
(key, _) if pat_is_wild(key, body) => (&pat[1].span, "values"),
603-
(_, value) if pat_is_wild(value, body) => (&pat[0].span, "keys"),
603+
let (new_pat_span, kind) = match (&pat[0].node, &pat[1].node) {
604+
(key, _) if pat_is_wild(key, body) => (pat[1].span, "value"),
605+
(_, value) if pat_is_wild(value, body) => (pat[0].span, "key"),
604606
_ => return,
605607
};
606608

607-
let arg_span = match arg.node {
608-
ExprAddrOf(MutImmutable, ref expr) => expr.span,
609+
let (arg_span, arg) = match arg.node {
610+
ExprAddrOf(MutImmutable, ref expr) => (arg.span, &**expr),
609611
ExprAddrOf(MutMutable, _) => return, // for _ in &mut _, there is no {values,keys}_mut method
610-
_ => arg.span,
612+
_ => (arg.span, arg),
611613
};
612614

613615
let ty = walk_ptrs_ty(cx.tcx.expr_ty(arg));
614616
if match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::BTREEMAP) {
615617
span_lint_and_then(cx,
616618
FOR_KV_MAP,
617619
expr.span,
618-
&format!("you seem to want to iterate on a map's {}", kind),
620+
&format!("you seem to want to iterate on a map's {}s", kind),
619621
|db| {
620-
db.span_suggestion(expr.span,
621-
"use the corresponding method",
622-
format!("for {} in {}.{}() {{ .. }}",
623-
snippet(cx, *pat_span, ".."),
624-
snippet(cx, arg_span, ".."),
625-
kind));
622+
let map = sugg::Sugg::hir(cx, arg, "map");
623+
multispan_sugg(db, "use the corresponding method".into(), &[
624+
(pat_span, &snippet(cx, new_pat_span, kind)),
625+
(arg_span, &format!("{}.{}s()", map.maybe_par(), kind)),
626+
]);
626627
});
627628
}
628629
}

clippy_lints/src/transmute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl LateLintPass for Transmute {
149149
from_ty,
150150
to_ty),
151151
|db| {
152-
let arg = &sugg::Sugg::hir(cx, &args[0], "..");
152+
let arg = sugg::Sugg::hir(cx, &args[0], "..");
153153
let (deref, cast) = if to_rty.mutbl == Mutability::MutMutable {
154154
("&mut *", "*mut")
155155
} else {

clippy_lints/src/utils/sugg.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl<'a> Sugg<'a> {
121121

122122
/// Convenience method to create the `&<expr>` suggestion.
123123
pub fn addr(self) -> Sugg<'static> {
124-
make_unop("&", &self)
124+
make_unop("&", self)
125125
}
126126

127127
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` suggestion.
@@ -131,6 +131,15 @@ impl<'a> Sugg<'a> {
131131
ast::RangeLimits::Closed => make_assoc(AssocOp::DotDotDot, &self, &end),
132132
}
133133
}
134+
135+
/// Add parenthesis to any expression that might need them. Suitable to the `self` argument of
136+
/// a method call (eg. to build `bar.foo()` or `(1 + 2).foo()`).
137+
pub fn maybe_par(self) -> Self {
138+
match self {
139+
Sugg::NonParen(..) => self,
140+
Sugg::MaybeParen(sugg) | Sugg::BinOp(_, sugg) => Sugg::NonParen(format!("({})", sugg).into()),
141+
}
142+
}
134143
}
135144

136145
impl<'a, 'b> std::ops::Add<Sugg<'b>> for Sugg<'a> {
@@ -150,7 +159,7 @@ impl<'a, 'b> std::ops::Sub<Sugg<'b>> for Sugg<'a> {
150159
impl<'a> std::ops::Not for Sugg<'a> {
151160
type Output = Sugg<'static>;
152161
fn not(self) -> Sugg<'static> {
153-
make_unop("!", &self)
162+
make_unop("!", self)
154163
}
155164
}
156165

@@ -178,13 +187,12 @@ impl<T: std::fmt::Display> std::fmt::Display for ParenHelper<T> {
178187
}
179188
}
180189

181-
/// Build the string for `<op> <expr>` adding parenthesis when necessary.
190+
/// Build the string for `<op><expr>` adding parenthesis when necessary.
182191
///
183192
/// For convenience, the operator is taken as a string because all unary operators have the same
184193
/// precedence.
185-
pub fn make_unop(op: &str, expr: &Sugg) -> Sugg<'static> {
186-
let needs_paren = !matches!(*expr, Sugg::NonParen(..));
187-
Sugg::MaybeParen(format!("{}{}", op, ParenHelper::new(needs_paren, expr)).into())
194+
pub fn make_unop(op: &str, expr: Sugg) -> Sugg<'static> {
195+
Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into())
188196
}
189197

190198
/// Build the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.

tests/compile-fail/for_loop.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![plugin(clippy)]
33

44
use std::collections::*;
5+
use std::rc::Rc;
56

67
static STATIC: [usize; 4] = [ 0, 1, 8, 16 ];
78
const CONST: [usize; 4] = [ 0, 1, 8, 16 ];
@@ -388,8 +389,20 @@ fn main() {
388389
for (_, v) in &m {
389390
//~^ you seem to want to iterate on a map's values
390391
//~| HELP use the corresponding method
391-
//~| SUGGESTION for v in m.values()
392+
//~| HELP use the corresponding method
393+
//~| SUGGESTION for v in m.values() {
394+
let _v = v;
395+
}
396+
397+
let m : Rc<HashMap<u64, u64>> = Rc::new(HashMap::new());
398+
for (_, v) in &*m {
399+
//~^ you seem to want to iterate on a map's values
400+
//~| HELP use the corresponding method
401+
//~| HELP use the corresponding method
402+
//~| SUGGESTION for v in (*m).values() {
392403
let _v = v;
404+
// Here the `*` is not actually necesarry, but the test tests that we don't suggest
405+
// `in *m.values()` as we used to
393406
}
394407

395408
let mut m : HashMap<u64, u64> = HashMap::new();
@@ -403,7 +416,8 @@ fn main() {
403416
for (k, _value) in rm {
404417
//~^ you seem to want to iterate on a map's keys
405418
//~| HELP use the corresponding method
406-
//~| SUGGESTION for k in rm.keys()
419+
//~| HELP use the corresponding method
420+
//~| SUGGESTION for k in rm.keys() {
407421
let _k = k;
408422
}
409423

0 commit comments

Comments
 (0)