mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
0af72af1b8
Avoid redundant clone suggestions in borrowck diagnostics Fixes rust-lang/rust#153886 Removed redundant `.clone()` suggestions. I found that there are two patterns to handle this issue while I was implementing: - Should suggest only UFCS - Should suggest only simple `.clone()` For the target issue, we can just remove the UFCS (`<Option<String> as Clone>::clone(&selection.1)`) side. However, for the `BorrowedContentSource::OverloadedDeref` pattern like `Rc<Vec<i32>>`, for instance the `borrowck-move-out-of-overloaded-auto-deref.rs` test case, I think we need to employ the UFCS way. The actual test case is: ```rust //@ run-rustfix use std::rc::Rc; pub fn main() { let _x = Rc::new(vec![1, 2]).into_iter(); //~^ ERROR [E0507] } ``` And another error will be shown if we simply use the simple `.clone()` pattern. Like: ```rust use std::rc::Rc; pub fn main() { let _x = Rc::new(vec![1, 2]).clone().into_iter(); } ``` then we will get ``` error[E0507]: cannot move out of an `Rc` --> src/main.rs:5:14 | 5 | let _x = Rc::new(vec![1, 2]).clone().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ----------- value moved due to this method call | | | move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait | note: `into_iter` takes ownership of the receiver `self`, which moves value --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:310:18 | 310 | fn into_iter(self) -> Self::IntoIter; | ^^^^ help: you can `clone` the value and consume it, but this might not be your desired behavior | 5 - let _x = Rc::new(vec![1, 2]).clone().into_iter(); 5 + let _x = <Vec<i32> as Clone>::clone(&Rc::new(vec![1, 2])).into_iter(); | For more information about this error, try `rustc --explain E0507`. ``` [Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=7e767bed3f1c573c03642f20f454ed03) In this case, `Rc::clone` only increments the reference count and returns a new `Rc<Vec<i32>>`; it does not grant ownership of the inner `Vec<i32>`. As a result, calling into_iter() attempts to move the `Vec<i32>`, leading to the same E0507 error again. On the other hand, in UFCS form: ``` <Vec<i32> as Clone>::clone(&Rc::new(vec![1, 2])).into_iter() ``` This explicitly calls `<Vec<i32> as Clone>::clone`, and the argument `&Rc<Vec<i32>>` is treated as `&Vec<i32>` via Rc’s `Deref` implementation. As a result, the `Vec<i32>` itself is cloned, yielding an owned `Vec<i32>`, which allows `into_iter()` to succeed, if my understanding is correct. I addressed the issue as far as I could find the edge cases but please advice me if I'm overlooking something.