Skip to content

Commit

Permalink
rename function, recursively call peel_non_expn_blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Jul 9, 2023
1 parent 53f57b1 commit a68923d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 7 deletions.
9 changes: 6 additions & 3 deletions clippy_lints/src/methods/format_collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ use rustc_hir::LangItem;
use rustc_lint::LateContext;
use rustc_span::Span;

fn tail_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
/// Same as `peel_blocks` but only actually considers blocks that are not from an expansion.
/// This is needed because always calling `peel_blocks` would otherwise remove parts of the
/// `format!` macro, which would cause `root_macro_call_first_node` to return `None`.
fn peel_non_expn_blocks<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
match expr.kind {
ExprKind::Block(block, _) if !expr.span.from_expansion() => block.expr,
ExprKind::Block(block, _) if !expr.span.from_expansion() => peel_non_expn_blocks(block.expr?),
_ => Some(expr),
}
}
Expand All @@ -20,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, map_arg: &Expr<'_>, m
if is_type_lang_item(cx, cx.typeck_results().expr_ty(expr), LangItem::String)
&& let ExprKind::Closure(closure) = map_arg.kind
&& let body = cx.tcx.hir().body(closure.body)
&& let Some(value) = tail_expr(body.value)
&& let Some(value) = peel_non_expn_blocks(body.value)
&& let Some(mac) = root_macro_call_first_node(cx, value)
&& is_format_macro(cx, mac.def_id)
{
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/format_collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ fn hex_encode(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02X}")).collect()
}

#[rustfmt::skip]
fn hex_encode_deep(bytes: &[u8]) -> String {
bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect()
}

macro_rules! fmt {
($x:ident) => {
format!("{x:02X}", x = $x)
Expand Down
26 changes: 22 additions & 4 deletions tests/ui/format_collect.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,25 @@ LL | bytes.iter().map(|b| format!("{b:02X}")).collect()
= note: `-D clippy::format-collect` implied by `-D warnings`

error: use of `format!` to build up a string from an iterator
--> $DIR/format_collect.rs:19:5
--> $DIR/format_collect.rs:10:5
|
LL | bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: call `fold` instead
--> $DIR/format_collect.rs:10:18
|
LL | bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect()
| ^^^
help: ... and use the `write!` macro here
--> $DIR/format_collect.rs:10:32
|
LL | bytes.iter().map(|b| {{{{{ format!("{b:02X}") }}}}}).collect()
| ^^^^^^^^^^^^^^^^^^
= note: this can be written more efficiently by appending to a `String` directly

error: use of `format!` to build up a string from an iterator
--> $DIR/format_collect.rs:24:5
|
LL | / (1..10)
LL | | .map(|s| {
Expand All @@ -29,16 +47,16 @@ LL | | .collect()
| |__________________^
|
help: call `fold` instead
--> $DIR/format_collect.rs:20:10
--> $DIR/format_collect.rs:25:10
|
LL | .map(|s| {
| ^^^
help: ... and use the `write!` macro here
--> $DIR/format_collect.rs:22:13
--> $DIR/format_collect.rs:27:13
|
LL | format!("{s} {y}")
| ^^^^^^^^^^^^^^^^^^
= note: this can be written more efficiently by appending to a `String` directly

error: aborting due to 2 previous errors
error: aborting due to 3 previous errors

0 comments on commit a68923d

Please sign in to comment.