diff options
| author | Tyler Mandry <tmandry@gmail.com> | 2020-01-24 00:30:53 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-01-24 00:30:53 -0800 |
| commit | eb769ed6b09cb9fa007508caef808f5e50264cb0 (patch) | |
| tree | 19390f81a3749210c1c1f86154e697871405c764 | |
| parent | 62f227b3f822a27bd603acede9137bfb49ca8b68 (diff) | |
| parent | 6eaf59dfc8be4ee5647f9c090c5a7668682f30c0 (diff) | |
| download | rust-eb769ed6b09cb9fa007508caef808f5e50264cb0.tar.gz rust-eb769ed6b09cb9fa007508caef808f5e50264cb0.zip | |
Rollup merge of #68424 - estebank:suggest-borrow-for-non-copy-vec, r=davidtwco
Suggest borrowing `Vec<NonCopy>` in for loop Partially address #64167.
| -rw-r--r-- | src/libcore/option.rs | 1 | ||||
| -rw-r--r-- | src/libcore/result.rs | 1 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/diagnostics/move_errors.rs | 29 | ||||
| -rw-r--r-- | src/test/ui/suggestions/for-i-in-vec.fixed | 15 | ||||
| -rw-r--r-- | src/test/ui/suggestions/for-i-in-vec.rs | 15 | ||||
| -rw-r--r-- | src/test/ui/suggestions/for-i-in-vec.stderr | 12 |
6 files changed, 69 insertions, 4 deletions
diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a471b174534..cb4247d9874 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -151,6 +151,7 @@ use crate::{ /// The `Option` type. See [the module level documentation](index.html) for more. #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] +#[rustc_diagnostic_item = "option_type"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option<T> { /// No value diff --git a/src/libcore/result.rs b/src/libcore/result.rs index c657ce33f60..bc70dbd62eb 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -242,6 +242,7 @@ use crate::ops::{self, Deref, DerefMut}; /// [`Err`]: enum.Result.html#variant.Err #[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use = "this `Result` may be an `Err` variant, which should be handled"] +#[rustc_diagnostic_item = "result_type"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Result<T, E> { /// Contains the success value diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index eb6db7c145c..43121b38da0 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -1,7 +1,8 @@ use rustc::mir::*; use rustc::ty; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_span::Span; +use rustc_span::source_map::DesugaringKind; +use rustc_span::{Span, Symbol}; use crate::borrow_check::diagnostics::UseSpans; use crate::borrow_check::prefixes::PrefixSet; @@ -383,10 +384,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } }; - let move_ty = format!("{:?}", move_place.ty(*self.body, self.infcx.tcx).ty,); if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { - let is_option = move_ty.starts_with("std::option::Option"); - let is_result = move_ty.starts_with("std::result::Result"); + let def_id = match move_place.ty(*self.body, self.infcx.tcx).ty.kind { + ty::Adt(self_def, _) => self_def.did, + ty::Foreign(def_id) + | ty::FnDef(def_id, _) + | ty::Closure(def_id, _) + | ty::Generator(def_id, ..) + | ty::Opaque(def_id, _) => def_id, + _ => return err, + }; + let is_option = + self.infcx.tcx.is_diagnostic_item(Symbol::intern("option_type"), def_id); + let is_result = + self.infcx.tcx.is_diagnostic_item(Symbol::intern("result_type"), def_id); if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) { err.span_suggestion( span, @@ -397,6 +408,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { format!("{}.as_ref()", snippet), Applicability::MaybeIncorrect, ); + } else if span.is_desugaring(DesugaringKind::ForLoop) + && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) + { + // 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..576a7cc2f60 --- /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`. |
