Skip to content

Commit 00a2616

Browse files
committed
Fix range_minus_one and range_plus_one clippy lints
1 parent d9ac2be commit 00a2616

File tree

4 files changed

+155
-60
lines changed

4 files changed

+155
-60
lines changed

src/tools/clippy/clippy_lints/src/ranges.rs

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_the
33
use clippy_utils::higher;
44
use clippy_utils::msrvs::{self, Msrv};
55
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
6-
use clippy_utils::sugg::Sugg;
76
use clippy_utils::{get_parent_expr, in_constant, is_integer_const, path_to_local};
87
use if_chain::if_chain;
98
use rustc_ast::ast::RangeLimits;
@@ -356,6 +355,8 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
356355
end: Some(end),
357356
limits: RangeLimits::HalfOpen
358357
}) = higher::Range::hir(expr);
358+
if start.map_or(true, |start| start.span.can_be_used_for_suggestions());
359+
if end.span.can_be_used_for_suggestions();
359360
if let Some(y) = y_plus_one(cx, end);
360361
then {
361362
let span = expr.span;
@@ -365,25 +366,19 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
365366
span,
366367
"an inclusive range would be more readable",
367368
|diag| {
368-
let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
369-
let end = Sugg::hir(cx, y, "y").maybe_par();
370-
if let Some(is_wrapped) = &snippet_opt(cx, span) {
371-
if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') {
372-
diag.span_suggestion(
373-
span,
374-
"use",
375-
format!("({start}..={end})"),
376-
Applicability::MaybeIncorrect,
377-
);
378-
} else {
379-
diag.span_suggestion(
380-
span,
381-
"use",
382-
format!("{start}..={end}"),
383-
Applicability::MachineApplicable, // snippet
384-
);
385-
}
386-
}
369+
diag.multipart_suggestion(
370+
"use an inclusive range instead",
371+
vec![
372+
(
373+
start.map(|s| s.span.shrink_to_hi())
374+
.unwrap_or(expr.span)
375+
.until(end.span),
376+
"..=".to_string(),
377+
),
378+
(y, String::new()),
379+
],
380+
Applicability::MachineApplicable,
381+
);
387382
},
388383
);
389384
}
@@ -392,9 +387,12 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
392387

393388
// inclusive range minus one: `x..=(y-1)`
394389
fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
390+
395391
if_chain! {
396392
if expr.span.can_be_used_for_suggestions();
397393
if let Some(higher::Range { start, end: Some(end), limits: RangeLimits::Closed }) = higher::Range::hir(expr);
394+
if start.map_or(true, |start| start.span.can_be_used_for_suggestions());
395+
if end.span.can_be_used_for_suggestions();
398396
if let Some(y) = y_minus_one(cx, end);
399397
then {
400398
span_lint_and_then(
@@ -403,13 +401,18 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
403401
expr.span,
404402
"an exclusive range would be more readable",
405403
|diag| {
406-
let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").maybe_par().to_string());
407-
let end = Sugg::hir(cx, y, "y").maybe_par();
408-
diag.span_suggestion(
409-
expr.span,
410-
"use",
411-
format!("{start}..{end}"),
412-
Applicability::MachineApplicable, // snippet
404+
diag.multipart_suggestion(
405+
"use an exclusive range instead",
406+
vec![
407+
(
408+
start.map(|s| s.span.shrink_to_hi())
409+
.unwrap_or(expr.span)
410+
.until(end.span),
411+
"..".to_string(),
412+
),
413+
(y, String::new()),
414+
],
415+
Applicability::MachineApplicable,
413416
);
414417
},
415418
);
@@ -497,19 +500,24 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
497500
}
498501
}
499502

500-
fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
503+
fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<Span> {
501504
match expr.kind {
502505
ExprKind::Binary(
503506
Spanned {
504-
node: BinOpKind::Add, ..
507+
node: BinOpKind::Add,
508+
span,
505509
},
506510
lhs,
507511
rhs,
508512
) => {
509-
if is_integer_const(cx, lhs, 1) {
510-
Some(rhs)
511-
} else if is_integer_const(cx, rhs, 1) {
512-
Some(lhs)
513+
if is_integer_const(cx, lhs, 1)
514+
&& lhs.span.peel_ctxt().ctxt() == span.peel_ctxt().ctxt()
515+
{
516+
Some(lhs.span.to(span))
517+
} else if is_integer_const(cx, rhs, 1)
518+
&& rhs.span.peel_ctxt().ctxt() == span.peel_ctxt().ctxt()
519+
{
520+
Some(span.to(rhs.span))
513521
} else {
514522
None
515523
}
@@ -518,15 +526,18 @@ fn y_plus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'
518526
}
519527
}
520528

521-
fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<&'t Expr<'t>> {
529+
fn y_minus_one<'t>(cx: &LateContext<'_>, expr: &'t Expr<'_>) -> Option<Span> {
522530
match expr.kind {
523531
ExprKind::Binary(
524532
Spanned {
525-
node: BinOpKind::Sub, ..
533+
node: BinOpKind::Sub,
534+
span,
526535
},
527-
lhs,
536+
_,
528537
rhs,
529-
) if is_integer_const(cx, rhs, 1) => Some(lhs),
538+
) if is_integer_const(cx, rhs, 1)
539+
&& rhs.span.peel_ctxt().ctxt() == span.peel_ctxt().ctxt()
540+
=> Some(span.to(rhs.span)),
530541
_ => None,
531542
}
532543
}

src/tools/clippy/tests/ui/range_plus_minus_one.fixed

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
// run-rustfix
22

33
#![allow(unused_parens)]
4-
#![allow(clippy::iter_with_drain)]
4+
#![allow(clippy::iter_with_drain, clippy::needless_parens_on_range_literals)]
55
fn f() -> usize {
66
42
77
}
88

99
macro_rules! macro_plus_one {
1010
($m: literal) => {
11-
for i in 0..$m + 1 {
11+
for i in 0..=$m {
1212
println!("{}", i);
1313
}
1414
};
1515
}
1616

1717
macro_rules! macro_minus_one {
1818
($m: literal) => {
19-
for i in 0..=$m - 1 {
19+
for i in 0..$m {
2020
println!("{}", i);
2121
}
2222
};
@@ -28,30 +28,30 @@ fn main() {
2828
for _ in 0..2 {}
2929
for _ in 0..=2 {}
3030

31-
for _ in 0..=3 {}
31+
for _ in 0..=3 {}
3232
for _ in 0..=3 + 1 {}
3333

34-
for _ in 0..=5 {}
34+
for _ in 0..= 5 {}
3535
for _ in 0..=1 + 5 {}
3636

37-
for _ in 1..=1 {}
37+
for _ in 1..= 1 {}
3838
for _ in 1..=1 + 1 {}
3939

4040
for _ in 0..13 + 13 {}
4141
for _ in 0..=13 - 7 {}
4242

43-
for _ in 0..=f() {}
43+
for _ in 0..=( f()) {}
4444
for _ in 0..=(1 + f()) {}
4545

4646
let _ = ..11 - 1;
47-
let _ = ..11;
48-
let _ = ..11;
49-
let _ = (1..=11);
50-
let _ = ((f() + 1)..=f());
47+
let _ = ..11 ;
48+
let _ = ..(11 );
49+
let _ = (1..=11 );
50+
let _ = (f() + 1)..=(f() );
5151

5252
const ONE: usize = 1;
5353
// integer consts are linted, too
54-
for _ in 1..=ONE {}
54+
for _ in 1..= ONE {}
5555

5656
let mut vec: Vec<()> = std::vec::Vec::new();
5757
vec.drain(..);

src/tools/clippy/tests/ui/range_plus_minus_one.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// run-rustfix
22

33
#![allow(unused_parens)]
4-
#![allow(clippy::iter_with_drain)]
4+
#![allow(clippy::iter_with_drain, clippy::needless_parens_on_range_literals)]
55
fn f() -> usize {
66
42
77
}

src/tools/clippy/tests/ui/range_plus_minus_one.stderr

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,143 @@ error: an inclusive range would be more readable
22
--> $DIR/range_plus_minus_one.rs:31:14
33
|
44
LL | for _ in 0..3 + 1 {}
5-
| ^^^^^^^^ help: use: `0..=3`
5+
| ^^^^^^^^
66
|
77
= note: `-D clippy::range-plus-one` implied by `-D warnings`
8+
help: use an inclusive range instead
9+
|
10+
LL - for _ in 0..3 + 1 {}
11+
LL + for _ in 0..=3 {}
12+
|
813

914
error: an inclusive range would be more readable
1015
--> $DIR/range_plus_minus_one.rs:34:14
1116
|
1217
LL | for _ in 0..1 + 5 {}
13-
| ^^^^^^^^ help: use: `0..=5`
18+
| ^^^^^^^^
19+
|
20+
help: use an inclusive range instead
21+
|
22+
LL - for _ in 0..1 + 5 {}
23+
LL + for _ in 0..= 5 {}
24+
|
1425

1526
error: an inclusive range would be more readable
1627
--> $DIR/range_plus_minus_one.rs:37:14
1728
|
1829
LL | for _ in 1..1 + 1 {}
19-
| ^^^^^^^^ help: use: `1..=1`
30+
| ^^^^^^^^
31+
|
32+
help: use an inclusive range instead
33+
|
34+
LL - for _ in 1..1 + 1 {}
35+
LL + for _ in 1..= 1 {}
36+
|
2037

2138
error: an inclusive range would be more readable
2239
--> $DIR/range_plus_minus_one.rs:43:14
2340
|
2441
LL | for _ in 0..(1 + f()) {}
25-
| ^^^^^^^^^^^^ help: use: `0..=f()`
42+
| ^^^^^^^^^^^^
43+
|
44+
help: use an inclusive range instead
45+
|
46+
LL - for _ in 0..(1 + f()) {}
47+
LL + for _ in 0..=( f()) {}
48+
|
2649

2750
error: an exclusive range would be more readable
2851
--> $DIR/range_plus_minus_one.rs:47:13
2952
|
3053
LL | let _ = ..=11 - 1;
31-
| ^^^^^^^^^ help: use: `..11`
54+
| ^^^^^^^^^
3255
|
3356
= note: `-D clippy::range-minus-one` implied by `-D warnings`
57+
help: use an exclusive range instead
58+
|
59+
LL - let _ = ..=11 - 1;
60+
LL + let _ = ..11 ;
61+
|
3462

3563
error: an exclusive range would be more readable
3664
--> $DIR/range_plus_minus_one.rs:48:13
3765
|
3866
LL | let _ = ..=(11 - 1);
39-
| ^^^^^^^^^^^ help: use: `..11`
67+
| ^^^^^^^^^^^
68+
|
69+
help: use an exclusive range instead
70+
|
71+
LL - let _ = ..=(11 - 1);
72+
LL + let _ = ..(11 );
73+
|
4074

4175
error: an inclusive range would be more readable
4276
--> $DIR/range_plus_minus_one.rs:49:13
4377
|
4478
LL | let _ = (1..11 + 1);
45-
| ^^^^^^^^^^^ help: use: `(1..=11)`
79+
| ^^^^^^^^^^^
80+
|
81+
help: use an inclusive range instead
82+
|
83+
LL - let _ = (1..11 + 1);
84+
LL + let _ = (1..=11 );
85+
|
4686

4787
error: an inclusive range would be more readable
4888
--> $DIR/range_plus_minus_one.rs:50:13
4989
|
5090
LL | let _ = (f() + 1)..(f() + 1);
51-
| ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())`
91+
| ^^^^^^^^^^^^^^^^^^^^
92+
|
93+
help: use an inclusive range instead
94+
|
95+
LL - let _ = (f() + 1)..(f() + 1);
96+
LL + let _ = (f() + 1)..=(f() );
97+
|
5298

5399
error: an inclusive range would be more readable
54100
--> $DIR/range_plus_minus_one.rs:54:14
55101
|
56102
LL | for _ in 1..ONE + ONE {}
57-
| ^^^^^^^^^^^^ help: use: `1..=ONE`
103+
| ^^^^^^^^^^^^
104+
|
105+
help: use an inclusive range instead
106+
|
107+
LL - for _ in 1..ONE + ONE {}
108+
LL + for _ in 1..= ONE {}
109+
|
110+
111+
error: an inclusive range would be more readable
112+
--> $DIR/range_plus_minus_one.rs:11:18
113+
|
114+
LL | for i in 0..$m + 1 {
115+
| ^^^^^^^^^
116+
...
117+
LL | macro_plus_one!(5);
118+
| ------------------ in this macro invocation
119+
|
120+
= note: this error originates in the macro `macro_plus_one` (in Nightly builds, run with -Z macro-backtrace for more info)
121+
help: use an inclusive range instead
122+
|
123+
LL - for i in 0..$m + 1 {
124+
LL + for i in 0..=$m {
125+
|
126+
127+
error: an exclusive range would be more readable
128+
--> $DIR/range_plus_minus_one.rs:19:18
129+
|
130+
LL | for i in 0..=$m - 1 {
131+
| ^^^^^^^^^^
132+
...
133+
LL | macro_minus_one!(5);
134+
| ------------------- in this macro invocation
135+
|
136+
= note: this error originates in the macro `macro_minus_one` (in Nightly builds, run with -Z macro-backtrace for more info)
137+
help: use an exclusive range instead
138+
|
139+
LL - for i in 0..=$m - 1 {
140+
LL + for i in 0..$m {
141+
|
58142

59-
error: aborting due to 9 previous errors
143+
error: aborting due to 11 previous errors
60144

0 commit comments

Comments
 (0)