about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-01-21 11:11:00 -0800
committerEsteban Küber <esteban@kuber.com.ar>2020-01-21 11:11:00 -0800
commitc775927d7fee06743631d138eac91a862c8f6faf (patch)
tree3cd8ed63b9d3c2026c41db11e9a3f353499650c9
parent7da653f669dcb97d40ca29b2937518bb8a12b775 (diff)
downloadrust-c775927d7fee06743631d138eac91a862c8f6faf.tar.gz
rust-c775927d7fee06743631d138eac91a862c8f6faf.zip
Suggest borrowing `Vec<NonCopy>` in for loop
Partially address #64167.
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/move_errors.rs11
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.fixed15
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.rs15
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.stderr12
4 files changed, 53 insertions, 0 deletions
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index eb6db7c145c..c016cc90b1b 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -1,6 +1,7 @@
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_span::source_map::DesugaringKind;
 use rustc_span::Span;
 
 use crate::borrow_check::diagnostics::UseSpans;
@@ -397,6 +398,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     format!("{}.as_ref()", snippet),
                     Applicability::MaybeIncorrect,
                 );
+            } else if span.is_desugaring(DesugaringKind::ForLoop)
+                && move_ty.starts_with("std::vec::Vec")
+            {
+                // FIXME: suggest for anything that implements `IntoIterator`.
+                err.span_suggestion(
+                    span,
+                    "consider iterating over a slice of the `Vec`'s content",
+                    format!("&{}", snippet),
+                    Applicability::MaybeIncorrect,
+                );
             }
         }
         err
diff --git a/src/test/ui/suggestions/for-i-in-vec.fixed b/src/test/ui/suggestions/for-i-in-vec.fixed
new file mode 100644
index 00000000000..ec7358bd08a
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+    v: Vec<u32>,
+}
+
+impl Foo {
+    fn bar(&self) {
+        for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.rs b/src/test/ui/suggestions/for-i-in-vec.rs
new file mode 100644
index 00000000000..304fe8cc81f
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct Foo {
+    v: Vec<u32>,
+}
+
+impl Foo {
+    fn bar(&self) {
+        for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr
new file mode 100644
index 00000000000..0fd10489bd0
--- /dev/null
+++ b/src/test/ui/suggestions/for-i-in-vec.stderr
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of `self.v` which is behind a shared reference
+  --> $DIR/for-i-in-vec.rs:10:18
+   |
+LL |         for _ in self.v {
+   |                  ^^^^^^
+   |                  |
+   |                  move occurs because `self.v` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait
+   |                  help: consider iterating over a slice of the `Vec`'s content: `&self.v`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.