-#![warn(clippy::redundant_clone)]
+// run-rustfix
+// rustfix-only-machine-applicable
use std::ffi::OsString;
use std::path::Path;
fn main() {
- let _ = ["lorem", "ipsum"].join(" ").to_string();
+ let _s = ["lorem", "ipsum"].join(" ").to_string();
let s = String::from("foo");
- let _ = s.clone();
+ let _s = s.clone();
let s = String::from("foo");
- let _ = s.to_string();
+ let _s = s.to_string();
let s = String::from("foo");
- let _ = s.to_owned();
+ let _s = s.to_owned();
- let _ = Path::new("/a/b/").join("c").to_owned();
+ let _s = Path::new("/a/b/").join("c").to_owned();
- let _ = Path::new("/a/b/").join("c").to_path_buf();
+ let _s = Path::new("/a/b/").join("c").to_path_buf();
- let _ = OsString::new().to_owned();
+ let _s = OsString::new().to_owned();
- let _ = OsString::new().to_os_string();
+ let _s = OsString::new().to_os_string();
// Check that lint level works
#[allow(clippy::redundant_clone)]
- let _ = String::new().to_string();
+ let _s = String::new().to_string();
let tup = (String::from("foo"),);
- let _ = tup.0.clone();
+ let _t = tup.0.clone();
let tup_ref = &(String::from("foo"),);
let _s = tup_ref.0.clone(); // this `.clone()` cannot be removed
+
+ {
+ let x = String::new();
+ let y = &x;
+
+ let _x = x.clone(); // ok; `x` is borrowed by `y`
+
+ let _ = y.len();
+ }
+
+ let x = (String::new(),);
+ let _ = Some(String::new()).unwrap_or_else(|| x.0.clone()); // ok; closure borrows `x`
+
+ with_branch(Alpha, true);
+ cannot_double_move(Alpha);
+ cannot_move_from_type_with_drop();
+ borrower_propagation();
+ not_consumed();
+ issue_5405();
}
#[derive(Clone)]
}
}
+fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) {
+ (a.clone(), a)
+}
+
struct TypeWithDrop {
x: String,
}
let s = TypeWithDrop { x: String::new() };
s.x.clone() // removing this `clone()` summons E0509
}
+
+fn borrower_propagation() {
+ let s = String::new();
+ let t = String::new();
+
+ {
+ fn b() -> bool {
+ unimplemented!()
+ }
+ let _u = if b() { &s } else { &t };
+
+ // ok; `s` and `t` are possibly borrowed
+ let _s = s.clone();
+ let _t = t.clone();
+ }
+
+ {
+ let _u = || s.len();
+ let _v = [&t; 32];
+ let _s = s.clone(); // ok
+ let _t = t.clone(); // ok
+ }
+
+ {
+ let _u = {
+ let u = Some(&s);
+ let _ = s.clone(); // ok
+ u
+ };
+ let _s = s.clone(); // ok
+ }
+
+ {
+ use std::convert::identity as id;
+ let _u = id(id(&s));
+ let _s = s.clone(); // ok, `u` borrows `s`
+ }
+
+ let _s = s.clone();
+ let _t = t.clone();
+
+ #[derive(Clone)]
+ struct Foo {
+ x: usize,
+ }
+
+ {
+ let f = Foo { x: 123 };
+ let _x = Some(f.x);
+ let _f = f.clone();
+ }
+
+ {
+ let f = Foo { x: 123 };
+ let _x = &f.x;
+ let _f = f.clone(); // ok
+ }
+}
+
+fn not_consumed() {
+ let x = std::path::PathBuf::from("home");
+ let y = x.clone().join("matthias");
+ // join() creates a new owned PathBuf, does not take a &mut to x variable, thus the .clone() is
+ // redundant. (It also does not consume the PathBuf)
+
+ println!("x: {:?}, y: {:?}", x, y);
+
+ let mut s = String::new();
+ s.clone().push_str("foo"); // OK, removing this `clone()` will change the behavior.
+ s.push_str("bar");
+ assert_eq!(s, "bar");
+
+ let t = Some(s);
+ // OK
+ if let Some(x) = t.clone() {
+ println!("{}", x);
+ }
+ if let Some(x) = t {
+ println!("{}", x);
+ }
+}
+
+#[allow(clippy::clone_on_copy)]
+fn issue_5405() {
+ let a: [String; 1] = [String::from("foo")];
+ let _b: String = a[0].clone();
+
+ let c: [usize; 2] = [2, 3];
+ let _d: usize = c[1].clone();
+}