When moving out of a for loop head, suggest borrowing it
When encountering code like the following, suggest borrowing the for loop head to avoid moving it into the for loop pattern: ``` fn main() { let a = vec![1, 2, 3]; for i in &a { for j in a { println!("{} * {} = {}", i, j, i * j); } } } ```
This commit is contained in:
parent
c7b5f4d0f7
commit
ae883dc826
@ -4334,13 +4334,14 @@ impl<'a> LoweringContext<'a> {
|
||||
// }
|
||||
|
||||
// expand <head>
|
||||
let head = self.lower_expr(head);
|
||||
let mut head = self.lower_expr(head);
|
||||
let head_sp = head.span;
|
||||
let desugared_span = self.mark_span_with_reason(
|
||||
CompilerDesugaringKind::ForLoop,
|
||||
head_sp,
|
||||
None,
|
||||
);
|
||||
head.span = desugared_span;
|
||||
|
||||
let iter = self.str_to_ident("iter");
|
||||
|
||||
|
@ -34,6 +34,7 @@ use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syntax::source_map::CompilerDesugaringKind;
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
|
||||
use log::debug;
|
||||
@ -744,6 +745,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
|
||||
},
|
||||
moved_lp.ty));
|
||||
}
|
||||
if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = (
|
||||
move_span.compiler_desugaring_kind(),
|
||||
self.tcx.sess.source_map().span_to_snippet(move_span),
|
||||
) {
|
||||
if !snippet.starts_with("&") {
|
||||
err.span_suggestion(
|
||||
move_span,
|
||||
"consider borrowing this to avoid moving it into the for loop",
|
||||
format!("&{}", snippet),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Note: we used to suggest adding a `ref binding` or calling
|
||||
// `clone` but those suggestions have been removed because
|
||||
|
10
src/test/ui/suggestions/borrow-for-loop-head.rs
Normal file
10
src/test/ui/suggestions/borrow-for-loop-head.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3];
|
||||
for i in &a {
|
||||
for j in a {
|
||||
//~^ ERROR cannot move out of `a` because it is borrowed
|
||||
//~| ERROR use of moved value: `a`
|
||||
println!("{} * {} = {}", i, j, i * j);
|
||||
}
|
||||
}
|
||||
}
|
24
src/test/ui/suggestions/borrow-for-loop-head.stderr
Normal file
24
src/test/ui/suggestions/borrow-for-loop-head.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
error[E0505]: cannot move out of `a` because it is borrowed
|
||||
--> $DIR/borrow-for-loop-head.rs:4:18
|
||||
|
|
||||
LL | for i in &a {
|
||||
| - borrow of `a` occurs here
|
||||
LL | for j in a {
|
||||
| ^ move out of `a` occurs here
|
||||
|
||||
error[E0382]: use of moved value: `a`
|
||||
--> $DIR/borrow-for-loop-head.rs:4:18
|
||||
|
|
||||
LL | for j in a {
|
||||
| ^ value moved here in previous iteration of loop
|
||||
|
|
||||
= note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
|
||||
help: consider borrowing this to avoid moving it into the for loop
|
||||
|
|
||||
LL | for j in &a {
|
||||
| ^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0382, E0505.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
Loading…
Reference in New Issue
Block a user