diff options
| author | bors <bors@rust-lang.org> | 2023-11-24 17:15:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-11-24 17:15:33 +0000 |
| commit | 6cfbe5707546248487d09fc338598254f352edfc (patch) | |
| tree | 17ea07374502f001281905491daace9676214127 /clippy_lints | |
| parent | 3e7a63b8d1b56d4e8a440df81eea649c9d6926d7 (diff) | |
| parent | f9c6335a0f1a2a0fb17a67d0aa72eae63bbd8a3f (diff) | |
Auto merge of #11862 - christophbeberweil:7125-single-element-loop-over-range, r=llogiq
suggest alternatives to iterate an array of ranges
works towards #7125
changelog: [`single_element_loop`]: suggest better syntax when iterating over an array of a single range
`@thinkerdreamer` and myself worked on this issue during a workshop by `@llogiq` at the RustLab 2023 conference. It is our first contribution to clippy.
When iterating over an array of only one element, _which is a range_, our change suggests to replace the array with the contained range itself. Additionally, a hint is printed stating that the user probably intended to iterate over the range and not the array. If the single element in the array is not a range, the previous suggestion in the form of `let {pat_snip} = {prefix}{arg_snip};{block_str}`is used.
This change lints the array with the single range directly, so any prefixes or suffixes are covered as well.
Diffstat (limited to 'clippy_lints')
| -rw-r--r-- | clippy_lints/src/loops/single_element_loop.rs | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/clippy_lints/src/loops/single_element_loop.rs b/clippy_lints/src/loops/single_element_loop.rs index d860b297a02..4773a1454b7 100644 --- a/clippy_lints/src/loops/single_element_loop.rs +++ b/clippy_lints/src/loops/single_element_loop.rs @@ -1,6 +1,6 @@ use super::SINGLE_ELEMENT_LOOP; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::{indent_of, snippet_with_applicability}; +use clippy_utils::source::{indent_of, snippet, snippet_with_applicability}; use clippy_utils::visitors::contains_break_or_continue; use rustc_ast::util::parser::PREC_PREFIX; use rustc_ast::Mutability; @@ -87,14 +87,29 @@ pub(super) fn check<'tcx>( arg_snip = format!("({arg_snip})").into(); } - span_lint_and_sugg( - cx, - SINGLE_ELEMENT_LOOP, - expr.span, - "for loop over a single element", - "try", - format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"), - applicability, - ); + if clippy_utils::higher::Range::hir(arg_expression).is_some() { + let range_expr = snippet(cx, arg_expression.span, "?").to_string(); + + let sugg = snippet(cx, arg_expression.span, ".."); + span_lint_and_sugg( + cx, + SINGLE_ELEMENT_LOOP, + arg.span, + format!("this loops only once with `{pat_snip}` being `{range_expr}`").as_str(), + "did you mean to iterate over the range instead?", + sugg.to_string(), + Applicability::Unspecified, + ); + } else { + span_lint_and_sugg( + cx, + SINGLE_ELEMENT_LOOP, + expr.span, + "for loop over a single element", + "try", + format!("{{\n{indent}let {pat_snip} = {prefix}{arg_snip};{block_str}}}"), + applicability, + ); + } } } |
