New issues, Autofix, and new syntax support added to the Rust Analyzer

In the past couple of months, we have worked on adding over 40 issues to the Rust Analyzer, with a significant number of them supporting Autofix.

With the coming update, the Rust Analyzer checks for the fs::remove_dir_all ****vulnerability in the standard library, and also adds support for destructuring syntax introduced in Rust 1.58.

Newly added Issues:

RS-W1035: Found occurrence of .inspect(..).for_each(..)

Checks for calls to inspect followed by for_each.
The computation performed inside inspect could be moved into the
beginning of the closure in for_each.

/// Bad Practice
[1, 2, 3, 4, 5]
    .iter()
    .inspect(|x| println!("inspecting: {:?}", x))
    .for_each(|x| {
        // do_stuff
    });
/// Recommended
[1, 2, 3, 4, 5]
    .iter()
    .for_each(|x| {
        println!("inspecting: {:?}", x)
        // do_stuff
    });

RS-W1050: Found occurrence of &Box<T> or &mut Box<T>

&Box<T> or &mut Box<T> are often better written as &T or &mut T.

Any function that accepts &T as an argument, will also accept &Box<T>.
Box<T> implements Deref<Target = T>, which allows any &Box<T> to
automatically dereference to a &T.

/// Bad Practice
fn function(box_foo : &Box<Foo>) { ... }
/// Recommended
fn function(foo : &Foo) {}

RS-E1007: Found erasing operation

Checks for operations that evaluate to zero, such as 0 / y. This is most
likely unintentional.

/// Bad Practice
x * 0;
x & 0;
0 / x;
/// Recommended
0; // x * 0;
0; // x & 0;
0; // 0 / x;

RS-E1003: Found occurrence of .step_by(0)

Calling .step_by(0) on an iterator panics.

/// Bad Practice
[1, 2, 3].iter().step_by(0);

for _ in (0..100).step_by(0) {
    // ...
}

Newly added Autofixes:

RS-E1005: Found empty range expression

Ranges such as x..y where x is greater than y results in an empty range. Iterating over such ranges is a no-op. The likely intention would be iterating in reverse, in which case, (x..y).rev() must be used.

Autofix: Fix empty range with .rev()

fn function() {
++++ Fix empty range with `.rev()`
<   for x in 10..0 { ... }
>   for x in (0..10).rev() { ... }

++++ Fix empty range with `.rev()`
<   for x in 10..=0 { ... }
>   for x in (0..=10).rev() { ... }
}

RS-E1006: Found incorrect usage of #[inline] attribute

The #[inline] attribute has no effect when used on associated functions in
trait definitions. Only implementations may be inlined.

Autofix: Remove redundant #[inline] attribute

trait Foo {
++++ Remove redundant `#[inline]` attribute
<   #[inline] fn function();
>   fn function();
}

RS-W1036: Found occurrence of .skip(..).next()

.skip(..).next() is equivalent to .nth(..), which is more readable.

Autofix: Simplify .skip(..).next() with .nth(..)

fn function() {
++++ Simplify `.skip(..).next()` with `.nth(..)`
<   let x = a.skip(5).next();
>   let x = a.nth(5);

++++ Simplify `.skip(..).next()` with `.nth(..)`
<   let x = a
<      .iter()
<      .skip(5)
<      .next();
>   let x = a
>      .iter()
>      .nth(5);
}

…and many more! Check out the full list of Issues and Autofixes supported by the Rust Analyzer over at the Directory.