-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Suggest borrowing arguments in generic positions when trait bounds ar…
…e satisfied This subsumes the suggestions to borrow arguments with `AsRef`/`Borrow` bounds and those to borrow arguments with `Fn` and `FnMut` bounds. It works for other traits implemented on references as well, such as `std::io::Read`, `std::io::Write`, and `core::fmt::Write`. Incidentally, by making the logic for suggesting borrowing closures general, this removes some spurious suggestions to mutably borrow `FnMut` closures in assignments, as well as an unhelpful suggestion to add a `Clone` constraint to an `impl Fn` argument.
- Loading branch information
Showing
13 changed files
with
327 additions
and
300 deletions.
There are no files selected for viewing
316 changes: 157 additions & 159 deletions
316
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Large diffs are not rendered by default.
Oops, something went wrong.
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
27 changes: 12 additions & 15 deletions
27
tests/ui/moves/auxiliary/suggest-borrow-for-generic-arg-aux.rs
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 |
---|---|---|
@@ -1,23 +1,20 @@ | ||
//! auxiliary definitons for suggest-borrow-for-generic-arg.rs, to ensure the suggestion works on | ||
//! functions defined in other crates. | ||
use std::borrow::{Borrow, BorrowMut}; | ||
use std::convert::{AsMut, AsRef}; | ||
pub struct Bar; | ||
use std::io::{self, Read, Write}; | ||
use std::iter::Sum; | ||
|
||
impl AsRef<Bar> for Bar { | ||
fn as_ref(&self) -> &Bar { | ||
self | ||
} | ||
pub fn write_stuff<W: Write>(mut writer: W) -> io::Result<()> { | ||
writeln!(writer, "stuff") | ||
} | ||
|
||
impl AsMut<Bar> for Bar { | ||
fn as_mut(&mut self) -> &mut Bar { | ||
self | ||
} | ||
pub fn read_and_discard<R: Read>(mut reader: R) -> io::Result<()> { | ||
let mut buf = Vec::new(); | ||
reader.read_to_end(&mut buf).map(|_| ()) | ||
} | ||
|
||
pub fn foo<T: AsRef<Bar>>(_: T) {} | ||
pub fn qux<T: AsMut<Bar>>(_: T) {} | ||
pub fn bat<T: Borrow<T>>(_: T) {} | ||
pub fn baz<T: BorrowMut<T>>(_: T) {} | ||
pub fn sum_three<I: IntoIterator>(iter: I) -> <I as IntoIterator>::Item | ||
where <I as IntoIterator>::Item: Sum | ||
{ | ||
iter.into_iter().take(3).sum() | ||
} |
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 |
---|---|---|
@@ -1,22 +1,46 @@ | ||
//! Test suggetions to borrow generic arguments instead of moving when all predicates hold after | ||
//! substituting in the reference type. | ||
//! Test suggetions to borrow generic arguments instead of moving. Tests for other instances of this | ||
//! can be found in `moved-value-on-as-ref-arg.rs` and `borrow-closures-instead-of-move.rs` | ||
//@ run-rustfix | ||
//@ aux-build:suggest-borrow-for-generic-arg-aux.rs | ||
//@ aux-crate:aux=suggest-borrow-for-generic-arg-aux.rs | ||
//@ edition: 2021 | ||
|
||
#![allow(unused_mut)] | ||
extern crate suggest_borrow_for_generic_arg_aux as aux; | ||
use std::io::{self, Write}; | ||
|
||
pub fn main() { | ||
let bar = aux::Bar; | ||
aux::foo(&bar); //~ HELP consider borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let mut bar = aux::Bar; | ||
aux::qux(&mut bar); //~ HELP consider mutably borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let bar = aux::Bar; | ||
aux::bat(&bar); //~ HELP consider borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let mut bar = aux::Bar; | ||
aux::baz(&mut bar); //~ HELP consider mutably borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
// test for `std::io::Write` (#131413) | ||
fn test_write() -> io::Result<()> { | ||
let mut stdout = io::stdout(); | ||
aux::write_stuff(&stdout)?; //~ HELP consider borrowing `stdout` | ||
writeln!(stdout, "second line")?; //~ ERROR borrow of moved value: `stdout` | ||
|
||
let mut buf = Vec::new(); | ||
aux::write_stuff(&mut buf.clone())?; //~ HELP consider mutably borrowing `buf` | ||
//~^ HELP consider cloning the value | ||
writeln!(buf, "second_line") //~ ERROR borrow of moved value: `buf` | ||
} | ||
|
||
/// test for `std::io::Read` (#131413) | ||
fn test_read() -> io::Result<()> { | ||
let stdin = io::stdin(); | ||
aux::read_and_discard(&stdin)?; //~ HELP consider borrowing `stdin` | ||
aux::read_and_discard(stdin)?; //~ ERROR use of moved value: `stdin` | ||
|
||
let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]); | ||
aux::read_and_discard(&mut bytes.clone())?; //~ HELP consider mutably borrowing `bytes` | ||
//~^ HELP consider cloning the value | ||
aux::read_and_discard(bytes) //~ ERROR use of moved value: `bytes` | ||
} | ||
|
||
/// test that suggestions work with projection types in the callee's signature | ||
fn test_projections() { | ||
let mut iter = [1, 2, 3, 4, 5, 6].into_iter(); | ||
let _six: usize = aux::sum_three(&mut iter.clone()); //~ HELP consider mutably borrowing `iter` | ||
//~^ HELP consider cloning the value | ||
let _fifteen: usize = aux::sum_three(iter); //~ ERROR use of moved value: `iter` | ||
} | ||
|
||
fn main() { | ||
test_write().unwrap(); | ||
test_read().unwrap(); | ||
test_projections(); | ||
} |
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 |
---|---|---|
@@ -1,22 +1,46 @@ | ||
//! Test suggetions to borrow generic arguments instead of moving when all predicates hold after | ||
//! substituting in the reference type. | ||
//! Test suggetions to borrow generic arguments instead of moving. Tests for other instances of this | ||
//! can be found in `moved-value-on-as-ref-arg.rs` and `borrow-closures-instead-of-move.rs` | ||
//@ run-rustfix | ||
//@ aux-build:suggest-borrow-for-generic-arg-aux.rs | ||
//@ aux-crate:aux=suggest-borrow-for-generic-arg-aux.rs | ||
//@ edition: 2021 | ||
|
||
#![allow(unused_mut)] | ||
extern crate suggest_borrow_for_generic_arg_aux as aux; | ||
use std::io::{self, Write}; | ||
|
||
pub fn main() { | ||
let bar = aux::Bar; | ||
aux::foo(bar); //~ HELP consider borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let mut bar = aux::Bar; | ||
aux::qux(bar); //~ HELP consider mutably borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let bar = aux::Bar; | ||
aux::bat(bar); //~ HELP consider borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
let mut bar = aux::Bar; | ||
aux::baz(bar); //~ HELP consider mutably borrowing `bar` | ||
let _baa = bar; //~ ERROR use of moved value | ||
// test for `std::io::Write` (#131413) | ||
fn test_write() -> io::Result<()> { | ||
let mut stdout = io::stdout(); | ||
aux::write_stuff(stdout)?; //~ HELP consider borrowing `stdout` | ||
writeln!(stdout, "second line")?; //~ ERROR borrow of moved value: `stdout` | ||
|
||
let mut buf = Vec::new(); | ||
aux::write_stuff(buf)?; //~ HELP consider mutably borrowing `buf` | ||
//~^ HELP consider cloning the value | ||
writeln!(buf, "second_line") //~ ERROR borrow of moved value: `buf` | ||
} | ||
|
||
/// test for `std::io::Read` (#131413) | ||
fn test_read() -> io::Result<()> { | ||
let stdin = io::stdin(); | ||
aux::read_and_discard(stdin)?; //~ HELP consider borrowing `stdin` | ||
aux::read_and_discard(stdin)?; //~ ERROR use of moved value: `stdin` | ||
|
||
let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]); | ||
aux::read_and_discard(bytes)?; //~ HELP consider mutably borrowing `bytes` | ||
//~^ HELP consider cloning the value | ||
aux::read_and_discard(bytes) //~ ERROR use of moved value: `bytes` | ||
} | ||
|
||
/// test that suggestions work with projection types in the callee's signature | ||
fn test_projections() { | ||
let mut iter = [1, 2, 3, 4, 5, 6].into_iter(); | ||
let _six: usize = aux::sum_three(iter); //~ HELP consider mutably borrowing `iter` | ||
//~^ HELP consider cloning the value | ||
let _fifteen: usize = aux::sum_three(iter); //~ ERROR use of moved value: `iter` | ||
} | ||
|
||
fn main() { | ||
test_write().unwrap(); | ||
test_read().unwrap(); | ||
test_projections(); | ||
} |
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 |
---|---|---|
@@ -1,63 +1,93 @@ | ||
error[E0382]: use of moved value: `bar` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:12:16 | ||
error[E0382]: borrow of moved value: `stdout` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:14:14 | ||
| | ||
LL | let bar = aux::Bar; | ||
| --- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait | ||
LL | aux::foo(bar); | ||
| --- value moved here | ||
LL | let _baa = bar; | ||
| ^^^ value used here after move | ||
LL | let mut stdout = io::stdout(); | ||
| ---------- move occurs because `stdout` has type `Stdout`, which does not implement the `Copy` trait | ||
LL | aux::write_stuff(stdout)?; | ||
| ------ value moved here | ||
LL | writeln!(stdout, "second line")?; | ||
| ^^^^^^ value borrowed here after move | ||
| | ||
help: consider borrowing `bar` | ||
help: consider borrowing `stdout` | ||
| | ||
LL | aux::foo(&bar); | ||
| + | ||
LL | aux::write_stuff(&stdout)?; | ||
| + | ||
|
||
error[E0382]: use of moved value: `bar` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:15:16 | ||
error[E0382]: borrow of moved value: `buf` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:19:14 | ||
| | ||
LL | let mut bar = aux::Bar; | ||
| ------- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait | ||
LL | aux::qux(bar); | ||
| --- value moved here | ||
LL | let _baa = bar; | ||
| ^^^ value used here after move | ||
LL | let mut buf = Vec::new(); | ||
| ------- move occurs because `buf` has type `Vec<u8>`, which does not implement the `Copy` trait | ||
LL | aux::write_stuff(buf)?; | ||
| --- value moved here | ||
LL | | ||
LL | writeln!(buf, "second_line") | ||
| ^^^ value borrowed here after move | ||
| | ||
help: consider mutably borrowing `bar` | ||
help: consider mutably borrowing `buf` | ||
| | ||
LL | aux::qux(&mut bar); | ||
| ++++ | ||
LL | aux::write_stuff(&mut buf)?; | ||
| ++++ | ||
help: consider cloning the value if the performance cost is acceptable | ||
| | ||
LL | aux::write_stuff(buf.clone())?; | ||
| ++++++++ | ||
|
||
error[E0382]: use of moved value: `bar` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:18:16 | ||
error[E0382]: use of moved value: `stdin` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:26:27 | ||
| | ||
LL | let bar = aux::Bar; | ||
| --- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait | ||
LL | aux::bat(bar); | ||
| --- value moved here | ||
LL | let _baa = bar; | ||
| ^^^ value used here after move | ||
LL | let stdin = io::stdin(); | ||
| ----- move occurs because `stdin` has type `Stdin`, which does not implement the `Copy` trait | ||
LL | aux::read_and_discard(stdin)?; | ||
| ----- value moved here | ||
LL | aux::read_and_discard(stdin)?; | ||
| ^^^^^ value used here after move | ||
| | ||
help: consider borrowing `bar` | ||
help: consider borrowing `stdin` | ||
| | ||
LL | aux::bat(&bar); | ||
| + | ||
LL | aux::read_and_discard(&stdin)?; | ||
| + | ||
|
||
error[E0382]: use of moved value: `bar` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:21:16 | ||
error[E0382]: use of moved value: `bytes` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:31:27 | ||
| | ||
LL | let mut bytes = std::collections::VecDeque::from([1, 2, 3, 4, 5, 6]); | ||
| --------- move occurs because `bytes` has type `VecDeque<u8>`, which does not implement the `Copy` trait | ||
LL | aux::read_and_discard(bytes)?; | ||
| ----- value moved here | ||
LL | | ||
LL | aux::read_and_discard(bytes) | ||
| ^^^^^ value used here after move | ||
| | ||
help: consider mutably borrowing `bytes` | ||
| | ||
LL | aux::read_and_discard(&mut bytes)?; | ||
| ++++ | ||
help: consider cloning the value if the performance cost is acceptable | ||
| | ||
LL | aux::read_and_discard(bytes.clone())?; | ||
| ++++++++ | ||
|
||
error[E0382]: use of moved value: `iter` | ||
--> $DIR/suggest-borrow-for-generic-arg.rs:39:42 | ||
| | ||
LL | let mut iter = [1, 2, 3, 4, 5, 6].into_iter(); | ||
| -------- move occurs because `iter` has type `std::array::IntoIter<usize, 6>`, which does not implement the `Copy` trait | ||
LL | let _six: usize = aux::sum_three(iter); | ||
| ---- value moved here | ||
LL | | ||
LL | let _fifteen: usize = aux::sum_three(iter); | ||
| ^^^^ value used here after move | ||
| | ||
LL | let mut bar = aux::Bar; | ||
| ------- move occurs because `bar` has type `Bar`, which does not implement the `Copy` trait | ||
LL | aux::baz(bar); | ||
| --- value moved here | ||
LL | let _baa = bar; | ||
| ^^^ value used here after move | ||
help: consider mutably borrowing `iter` | ||
| | ||
help: consider mutably borrowing `bar` | ||
LL | let _six: usize = aux::sum_three(&mut iter); | ||
| ++++ | ||
help: consider cloning the value if the performance cost is acceptable | ||
| | ||
LL | aux::baz(&mut bar); | ||
| ++++ | ||
LL | let _six: usize = aux::sum_three(iter.clone()); | ||
| ++++++++ | ||
|
||
error: aborting due to 4 previous errors | ||
error: aborting due to 5 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0382`. |
Oops, something went wrong.