182 lines
3.9 KiB
Rust
182 lines
3.9 KiB
Rust
#![warn(clippy::range_minus_one, clippy::range_plus_one)]
|
|
#![allow(unused_parens)]
|
|
#![allow(clippy::iter_with_drain)]
|
|
|
|
use std::ops::{Index, IndexMut, Range, RangeBounds, RangeInclusive};
|
|
|
|
fn f() -> usize {
|
|
42
|
|
}
|
|
|
|
macro_rules! macro_plus_one {
|
|
($m: literal) => {
|
|
for i in 0..$m + 1 {
|
|
println!("{}", i);
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! macro_minus_one {
|
|
($m: literal) => {
|
|
for i in 0..=$m - 1 {
|
|
println!("{}", i);
|
|
}
|
|
};
|
|
}
|
|
|
|
fn main() {
|
|
for _ in 0..2 {}
|
|
for _ in 0..=2 {}
|
|
|
|
for _ in 0..=3 {}
|
|
//~^ range_plus_one
|
|
for _ in 0..=3 + 1 {}
|
|
|
|
for _ in 0..=5 {}
|
|
//~^ range_plus_one
|
|
for _ in 0..=1 + 5 {}
|
|
|
|
for _ in 1..=1 {}
|
|
//~^ range_plus_one
|
|
for _ in 1..=1 + 1 {}
|
|
|
|
for _ in 0..13 + 13 {}
|
|
for _ in 0..=13 - 7 {}
|
|
|
|
for _ in 0..=f() {}
|
|
//~^ range_plus_one
|
|
for _ in 0..=(1 + f()) {}
|
|
|
|
// Those are not linted, as in the general case we cannot be sure that the exact type won't be
|
|
// important.
|
|
let _ = ..11 - 1;
|
|
let _ = ..=11 - 1;
|
|
let _ = ..=(11 - 1);
|
|
let _ = (1..11 + 1);
|
|
let _ = (f() + 1)..(f() + 1);
|
|
|
|
const ONE: usize = 1;
|
|
// integer consts are linted, too
|
|
for _ in 1..=ONE {}
|
|
//~^ range_plus_one
|
|
|
|
let mut vec: Vec<()> = std::vec::Vec::new();
|
|
vec.drain(..);
|
|
|
|
macro_plus_one!(5);
|
|
macro_minus_one!(5);
|
|
|
|
// As an instance of `Iterator`
|
|
(1..=10).for_each(|_| {});
|
|
//~^ range_plus_one
|
|
|
|
// As an instance of `IntoIterator`
|
|
#[allow(clippy::useless_conversion)]
|
|
(1..=10).into_iter().for_each(|_| {});
|
|
//~^ range_plus_one
|
|
|
|
// As an instance of `RangeBounds`
|
|
{
|
|
let _ = (1..=10).start_bound();
|
|
//~^ range_plus_one
|
|
}
|
|
|
|
// As a `SliceIndex`
|
|
let a = [10, 20, 30];
|
|
let _ = &a[1..=1];
|
|
//~^ range_plus_one
|
|
|
|
// As method call argument
|
|
vec.drain(2..=3);
|
|
//~^ range_plus_one
|
|
|
|
// As function call argument
|
|
take_arg(10..=20);
|
|
//~^ range_plus_one
|
|
|
|
// As function call argument inside a block
|
|
take_arg({ 10..=20 });
|
|
//~^ range_plus_one
|
|
|
|
// Do not lint in case types are unified
|
|
take_arg(if true { 10..20 } else { 10..20 + 1 });
|
|
|
|
// Do not lint, as the same type is used for both parameters
|
|
take_args(10..20 + 1, 10..21);
|
|
|
|
// Do not lint, as the range type is also used indirectly in second parameter
|
|
take_arg_and_struct(10..20 + 1, S { t: 1..2 });
|
|
|
|
// As target of `IndexMut`
|
|
let mut a = [10, 20, 30];
|
|
a[0..=2][0] = 1;
|
|
//~^ range_plus_one
|
|
}
|
|
|
|
fn take_arg<T: Iterator<Item = u32>>(_: T) {}
|
|
fn take_args<T: Iterator<Item = u32>>(_: T, _: T) {}
|
|
|
|
struct S<T> {
|
|
t: T,
|
|
}
|
|
fn take_arg_and_struct<T: Iterator<Item = u32>>(_: T, _: S<T>) {}
|
|
|
|
fn no_index_by_range_inclusive(a: usize) {
|
|
struct S;
|
|
|
|
impl Index<Range<usize>> for S {
|
|
type Output = [u32];
|
|
fn index(&self, _: Range<usize>) -> &Self::Output {
|
|
&[]
|
|
}
|
|
}
|
|
|
|
_ = &S[0..a + 1];
|
|
}
|
|
|
|
fn no_index_mut_with_switched_range(a: usize) {
|
|
struct S(u32);
|
|
|
|
impl Index<Range<usize>> for S {
|
|
type Output = u32;
|
|
fn index(&self, _: Range<usize>) -> &Self::Output {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl IndexMut<Range<usize>> for S {
|
|
fn index_mut(&mut self, _: Range<usize>) -> &mut Self::Output {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
impl Index<RangeInclusive<usize>> for S {
|
|
type Output = u32;
|
|
fn index(&self, _: RangeInclusive<usize>) -> &Self::Output {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
S(2)[0..a + 1] = 3;
|
|
}
|
|
|
|
fn issue9908() {
|
|
// Simplified test case
|
|
let _ = || 0..=1;
|
|
|
|
// Original test case
|
|
let full_length = 1024;
|
|
let range = {
|
|
// do some stuff, omit here
|
|
None
|
|
};
|
|
|
|
let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length - 1));
|
|
|
|
assert_eq!(range, 0..=1023);
|
|
}
|
|
|
|
fn issue9908_2(n: usize) -> usize {
|
|
(1..n).sum()
|
|
//~^ range_minus_one
|
|
}
|