Skip to content

Commit 73a7363

Browse files
Add lint for string.extend(string.chars())
fixes #792
1 parent fa78b09 commit 73a7363

File tree

3 files changed

+34
-16
lines changed

3 files changed

+34
-16
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ name
327327
[single_match_else](https://github.com/Manishearth/rust-clippy/wiki#single_match_else) | allow | a match statement with a two arms where the second arm's pattern is a wildcard instead of `if let`
328328
[string_add](https://github.com/Manishearth/rust-clippy/wiki#string_add) | allow | using `x + ..` where x is a `String` instead of `push_str()`
329329
[string_add_assign](https://github.com/Manishearth/rust-clippy/wiki#string_add_assign) | allow | using `x = x + ..` where x is a `String` instead of `push_str()`
330-
[string_extend_chars](https://github.com/Manishearth/rust-clippy/wiki#string_extend_chars) | warn | using `x.extend(s.chars())` where s is a `&str`
330+
[string_extend_chars](https://github.com/Manishearth/rust-clippy/wiki#string_extend_chars) | warn | using `x.extend(s.chars())` where s is a `&str` or `String`
331331
[string_lit_as_bytes](https://github.com/Manishearth/rust-clippy/wiki#string_lit_as_bytes) | warn | calling `as_bytes` on a string literal instead of using a byte string literal
332332
[stutter](https://github.com/Manishearth/rust-clippy/wiki#stutter) | allow | type names prefixed/postfixed with their containing module's name
333333
[suspicious_assignment_formatting](https://github.com/Manishearth/rust-clippy/wiki#suspicious_assignment_formatting) | warn | suspicious formatting of `*=`, `-=` or `!=`

clippy_lints/src/methods.rs

+26-15
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ declare_lint! {
491491
}
492492

493493
/// **What it does:** Checks for the use of `.extend(s.chars())` where s is a
494-
/// `&str`.
494+
/// `&str` or `String`.
495495
///
496496
/// **Why is this bad?** `.push_str(s)` is clearer and faster
497497
///
@@ -500,20 +500,24 @@ declare_lint! {
500500
/// **Example:**
501501
/// ```rust
502502
/// let abc = "abc";
503+
/// let def = String::from("def");
503504
/// let mut s = String::new();
504505
/// s.extend(abc.chars());
506+
/// s.extend(def.chars());
505507
/// ```
506508
/// The correct use would be:
507509
/// ```rust
508510
/// let abc = "abc";
511+
/// let def = String::from("def");
509512
/// let mut s = String::new();
510513
/// s.push_str(abc);
514+
/// s.push_str(def.as_str());
511515
/// ```
512516
513517
declare_lint! {
514518
pub STRING_EXTEND_CHARS,
515519
Warn,
516-
"using `x.extend(s.chars())` where s is a `&str`"
520+
"using `x.extend(s.chars())` where s is a `&str` or `String`"
517521
}
518522

519523

@@ -839,19 +843,26 @@ fn lint_string_extend(cx: &LateContext, expr: &hir::Expr, args: &MethodArgs) {
839843
if let Some(arglists) = method_chain_args(arg, &["chars"]) {
840844
let target = &arglists[0][0];
841845
let (self_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(target));
842-
if self_ty.sty == ty::TyStr {
843-
span_lint_and_then(
844-
cx,
845-
STRING_EXTEND_CHARS,
846-
expr.span,
847-
"calling `.extend(_.chars())`",
848-
|db| {
849-
db.span_suggestion(expr.span, "try this",
850-
format!("{}.push_str({})",
851-
snippet(cx, args[0].span, "_"),
852-
snippet(cx, target.span, "_")));
853-
});
854-
}
846+
let extra_suggestion = if self_ty.sty == ty::TyStr {
847+
""
848+
} else if match_type(cx, self_ty, &paths::STRING) {
849+
".as_str()"
850+
} else {
851+
return;
852+
};
853+
854+
span_lint_and_then(
855+
cx,
856+
STRING_EXTEND_CHARS,
857+
expr.span,
858+
"calling `.extend(_.chars())`",
859+
|db| {
860+
db.span_suggestion(expr.span, "try this",
861+
format!("{}.push_str({}{})",
862+
snippet(cx, args[0].span, "_"),
863+
snippet(cx, target.span, "_"),
864+
extra_suggestion));
865+
});
855866
}
856867
}
857868

tests/compile-fail/methods.rs

+7
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ fn use_extend_from_slice() {
535535

536536
fn str_extend_chars() {
537537
let abc = "abc";
538+
let def = String::from("def");
538539
let mut s = String::new();
539540

540541
s.push_str(abc);
@@ -549,6 +550,12 @@ fn str_extend_chars() {
549550
//~|HELP try this
550551
//~|SUGGESTION s.push_str("abc")
551552

553+
s.push_str(def.as_str());
554+
s.extend(def.chars());
555+
//~^ERROR calling `.extend(_.chars())`
556+
//~|HELP try this
557+
//~|SUGGESTION s.push_str(def.as_str())
558+
552559
s.extend(abc.chars().skip(1));
553560
s.extend("abc".chars().skip(1));
554561
s.extend(['a', 'b', 'c'].iter());

0 commit comments

Comments
 (0)