-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #122254 - estebank:issue-48677, r=oli-obk
Detect calls to .clone() on T: !Clone types on borrowck errors When encountering a lifetime error on a type that *holds* a type that doesn't implement `Clone`, explore the item's body for potential calls to `.clone()` that are only cloning the reference `&T` instead of `T` because `T: !Clone`. If we find this, suggest `T: Clone`. ``` error[E0502]: cannot borrow `*list` as mutable because it is also borrowed as immutable --> $DIR/clone-on-ref.rs:7:5 | LL | for v in list.iter() { | ---- immutable borrow occurs here LL | cloned_items.push(v.clone()) | ------- this call doesn't do anything, the result is still `&T` because `T` doesn't implement `Clone` LL | } LL | list.push(T::default()); | ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here LL | LL | drop(cloned_items); | ------------ immutable borrow later used here | help: consider further restricting this bound | LL | fn foo<T: Default + Clone>(list: &mut Vec<T>) { | +++++++ ``` ``` error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/clone-on-ref.rs:23:10 | LL | fn qux(x: A) { | - binding `x` declared here LL | let a = &x; | -- borrow of `x` occurs here LL | let b = a.clone(); | ------- this call doesn't do anything, the result is still `&A` because `A` doesn't implement `Clone` LL | drop(x); | ^ move out of `x` occurs here LL | LL | println!("{b:?}"); | ----- borrow later used here | help: consider annotating `A` with `#[derive(Clone)]` | LL + #[derive(Clone)] LL | struct A; | ``` Fix #48677.
- Loading branch information
Showing
15 changed files
with
294 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
//@ run-rustfix | ||
fn foo<T: Default + Clone>(list: &mut Vec<T>) { | ||
let mut cloned_items = Vec::new(); | ||
for v in list.iter() { | ||
cloned_items.push(v.clone()) | ||
} | ||
list.push(T::default()); | ||
//~^ ERROR cannot borrow `*list` as mutable because it is also borrowed as immutable | ||
drop(cloned_items); | ||
} | ||
fn bar<T: std::fmt::Display + Clone>(x: T) { | ||
let a = &x; | ||
let b = a.clone(); | ||
drop(x); | ||
//~^ ERROR cannot move out of `x` because it is borrowed | ||
println!("{b}"); | ||
} | ||
#[derive(Debug)] | ||
#[derive(Clone)] | ||
struct A; | ||
fn qux(x: A) { | ||
let a = &x; | ||
let b = a.clone(); | ||
drop(x); | ||
//~^ ERROR cannot move out of `x` because it is borrowed | ||
println!("{b:?}"); | ||
} | ||
fn main() { | ||
foo(&mut vec![1, 2, 3]); | ||
bar(""); | ||
qux(A); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//@ run-rustfix | ||
fn foo<T: Default>(list: &mut Vec<T>) { | ||
let mut cloned_items = Vec::new(); | ||
for v in list.iter() { | ||
cloned_items.push(v.clone()) | ||
} | ||
list.push(T::default()); | ||
//~^ ERROR cannot borrow `*list` as mutable because it is also borrowed as immutable | ||
drop(cloned_items); | ||
} | ||
fn bar<T: std::fmt::Display>(x: T) { | ||
let a = &x; | ||
let b = a.clone(); | ||
drop(x); | ||
//~^ ERROR cannot move out of `x` because it is borrowed | ||
println!("{b}"); | ||
} | ||
#[derive(Debug)] | ||
struct A; | ||
fn qux(x: A) { | ||
let a = &x; | ||
let b = a.clone(); | ||
drop(x); | ||
//~^ ERROR cannot move out of `x` because it is borrowed | ||
println!("{b:?}"); | ||
} | ||
fn main() { | ||
foo(&mut vec![1, 2, 3]); | ||
bar(""); | ||
qux(A); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
error[E0502]: cannot borrow `*list` as mutable because it is also borrowed as immutable | ||
--> $DIR/clone-on-ref.rs:7:5 | ||
| | ||
LL | for v in list.iter() { | ||
| ---- immutable borrow occurs here | ||
LL | cloned_items.push(v.clone()) | ||
| ------- this call doesn't do anything, the result is still `&T` because `T` doesn't implement `Clone` | ||
LL | } | ||
LL | list.push(T::default()); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here | ||
LL | | ||
LL | drop(cloned_items); | ||
| ------------ immutable borrow later used here | ||
| | ||
help: consider further restricting this bound | ||
| | ||
LL | fn foo<T: Default + Clone>(list: &mut Vec<T>) { | ||
| +++++++ | ||
|
||
error[E0505]: cannot move out of `x` because it is borrowed | ||
--> $DIR/clone-on-ref.rs:14:10 | ||
| | ||
LL | fn bar<T: std::fmt::Display>(x: T) { | ||
| - binding `x` declared here | ||
LL | let a = &x; | ||
| -- borrow of `x` occurs here | ||
LL | let b = a.clone(); | ||
| ------- this call doesn't do anything, the result is still `&T` because `T` doesn't implement `Clone` | ||
LL | drop(x); | ||
| ^ move out of `x` occurs here | ||
LL | | ||
LL | println!("{b}"); | ||
| --- borrow later used here | ||
| | ||
help: consider further restricting this bound | ||
| | ||
LL | fn bar<T: std::fmt::Display + Clone>(x: T) { | ||
| +++++++ | ||
|
||
error[E0505]: cannot move out of `x` because it is borrowed | ||
--> $DIR/clone-on-ref.rs:23:10 | ||
| | ||
LL | fn qux(x: A) { | ||
| - binding `x` declared here | ||
LL | let a = &x; | ||
| -- borrow of `x` occurs here | ||
LL | let b = a.clone(); | ||
| ------- this call doesn't do anything, the result is still `&A` because `A` doesn't implement `Clone` | ||
LL | drop(x); | ||
| ^ move out of `x` occurs here | ||
LL | | ||
LL | println!("{b:?}"); | ||
| ----- borrow later used here | ||
| | ||
help: consider annotating `A` with `#[derive(Clone)]` | ||
| | ||
LL + #[derive(Clone)] | ||
LL | struct A; | ||
| | ||
|
||
error: aborting due to 3 previous errors | ||
|
||
Some errors have detailed explanations: E0502, E0505. | ||
For more information about an error, try `rustc --explain E0502`. |
Oops, something went wrong.