rust-lang / rust-lang/rust-clippy

new lint to remove redundant method calls that have no effect

Open
#16,099 3 comments 0 reactions 1 assignee View on GitHub

@S1gn3rs is already working on this.

Since May 7, 2026.

A-lint
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

What it does

Detect useless method calls like the second .trim() in string.trim().trim()

Advantage
  • Improve readability
  • (Possibly) improve performance
Drawbacks

No response

Example

I think covering all the examples below would be excessive, but I’ll list as many as I can think of anyway.

use std::cmp::Ordering;
use std::future::IntoFuture;
use std::net::{IpAddr, Ipv6Addr, TcpStream};
use std::process::Termination;
use std::thread::Builder;
use proc_macro::Span;

let mut vec = vec!['a', 'b', 'c'];

let _ = 1_i32.abs().abs();
let _ = 3.14_f32.floor().floor();
let _ = "Hello".trim().trim();
let _ = "Hello".to_lowercase().to_lowercase();
let _ = b"Hello".to_vec().to_vec();
let _ = (&0 as *const i32).cast::<u32>().cast::<u32>();
let _ = IpAddr::V6(Ipv6Addr::LOCALHOST).to_canonical().to_canonical();

// with arguments (be cautious of side effects)
let _ = 1_i32.max(0).max(0);
let _ = 1_i32.clamp(-1, 1).clamp(-1, 1);
let _ = vec.split_off(1).split_off(1);
let _ = Some(1).and(Some(1)).and(Some(1));
let _ = Ordering::Equal.then(Ordering::Less).then(Ordering::Less);

// rewriting might cause compilation errors (Wrap<Wrap<T>> -> Wrap<T>)
let _ = std::iter::once(1).cycle().cycle();
let _ = std::iter::once(Some(1)).fuse().fuse();
let _ = (0..).take(3).take(3);
let _ = (0..).peekable().peekable();

// some more weird examples for what it’s worth
let _ = Builder::new().stack_size(4096).stack_size(4096);
let _ = Err::<(), _>("oops").report().report();
let _ = Span::call_site().start().start();
let _ = TcpStream::connect("127.0.0.1:8080").as_socket().as_socket(); // Windows only
let _ = async {}.into_future().into_future();

Could be written as:

use std::cmp::Ordering;
use std::future::IntoFuture;
use std::net::{IpAddr, Ipv6Addr, TcpStream};
use std::process::Termination;
use std::thread::Builder;
use proc_macro::Span;

let mut vec = vec!['a', 'b', 'c'];

let _ = 1_i32.abs();
let _ = 3.14_f32.floor();
let _ = "Hello".trim();
let _ = "Hello".to_lowercase();
let _ = b"Hello".to_vec();
let _ = (&0 as *const i32).cast::<u32>();
let _ = IpAddr::V6(Ipv6Addr::LOCALHOST).to_canonical();

// with arguments (be cautious of side effects)
let _ = 1_i32.max(0);
let _ = 1_i32.clamp(-1, 1);
let _ = vec.split_off(1);
let _ = Some(1).and(Some(1));
let _ = Ordering::Equal.then(Ordering::Less);

// rewriting might cause compilation errors (Wrap<Wrap<T>> -> Wrap<T>)
let _ = std::iter::once(1).cycle();
let _ = std::iter::once(Some(1)).fuse();
let _ = (0..).take(3);
let _ = (0..).peekable();

// some more weird examples for what it’s worth
let _ = Builder::new().stack_size(4096);
let _ = Err::<(), _>("oops").report();
let _ = Span::call_site().start();
let _ = TcpStream::connect("127.0.0.1:8080").as_socket(); // Windows only
let _ = async {}.into_future();
Comparison with existing lints

redundant_clone catches useless .to_owned(), .to_string(), and .to_os_string()

#![warn(clippy::nursery)]

use std::ffi::OsStr;

fn main() {
    let _ = "Hello".to_owned().to_owned();
    let _ = 0.to_string().to_string();
    let _ = OsStr::new("foo").to_os_string().to_os_string();
}
warning: redundant clone
 --> src/main.rs:6:31
  |
6 |     let _ = "Hello".to_owned().to_owned();
  |                               ^^^^^^^^^^^ help: remove this
  |
note: this value is dropped without further use
 --> src/main.rs:6:13
  |
6 |     let _ = "Hello".to_owned().to_owned();
  |             ^^^^^^^^^^^^^^^^^^
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
note: the lint level is defined here
 --> src/main.rs:1:9
  |
1 | #![warn(clippy::nursery)]
  |         ^^^^^^^^^^^^^^^
  = note: `#[warn(clippy::redundant_clone)]` implied by `#[warn(clippy::nursery)]`

warning: redundant clone
 --> src/main.rs:7:26
  |
7 |     let _ = 0.to_string().to_string();
  |                          ^^^^^^^^^^^^ help: remove this
  |
note: this value is dropped without further use
 --> src/main.rs:7:13
  |
7 |     let _ = 0.to_string().to_string();
  |             ^^^^^^^^^^^^^
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone

warning: redundant clone
 --> src/main.rs:8:45
  |
8 |     let _ = OsStr::new("foo").to_os_string().to_os_string();
  |                                             ^^^^^^^^^^^^^^^ help: remove this
  |
note: this value is dropped without further use
 --> src/main.rs:8:13
  |
8 |     let _ = OsStr::new("foo").to_os_string().to_os_string();
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone

useless_conversion catches useless .into_iter() and From::from()

fn main() {
    let _ = Vec::<()>::new().into_iter().into_iter();
    let _ = String::from(String::from("Hello"));
}
warning: useless conversion to the same type: `std::vec::IntoIter<()>`
 --> src/main.rs:2:13
  |
2 |     let _ = Vec::<()>::new().into_iter().into_iter();
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `Vec::<()>::new().into_iter()`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
  = note: `#[warn(clippy::useless_conversion)]` on by default

warning: useless conversion to the same type: `std::string::String`
 --> src/main.rs:3:13
  |
3 |     let _ = String::from(String::from("Hello"));
  |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `String::from("Hello")`
  |
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#useless_conversion
Additional Context

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.