Skip to content

Commit f741f5e

Browse files
authored
Rollup merge of rust-lang#68424 - estebank:suggest-borrow-for-non-copy-vec, r=davidtwco
Suggest borrowing `Vec<NonCopy>` in for loop Partially address rust-lang#64167.
2 parents 2370109 + 6eaf59d commit f741f5e

File tree

6 files changed

+69
-4
lines changed

6 files changed

+69
-4
lines changed

src/libcore/option.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ use crate::{
151151

152152
/// The `Option` type. See [the module level documentation](index.html) for more.
153153
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
154+
#[rustc_diagnostic_item = "option_type"]
154155
#[stable(feature = "rust1", since = "1.0.0")]
155156
pub enum Option<T> {
156157
/// No value

src/libcore/result.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ use crate::ops::{self, Deref, DerefMut};
242242
/// [`Err`]: enum.Result.html#variant.Err
243243
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
244244
#[must_use = "this `Result` may be an `Err` variant, which should be handled"]
245+
#[rustc_diagnostic_item = "result_type"]
245246
#[stable(feature = "rust1", since = "1.0.0")]
246247
pub enum Result<T, E> {
247248
/// Contains the success value

src/librustc_mir/borrow_check/diagnostics/move_errors.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc::mir::*;
22
use rustc::ty;
33
use rustc_errors::{Applicability, DiagnosticBuilder};
4-
use rustc_span::Span;
4+
use rustc_span::source_map::DesugaringKind;
5+
use rustc_span::{Span, Symbol};
56

67
use crate::borrow_check::diagnostics::UseSpans;
78
use crate::borrow_check::prefixes::PrefixSet;
@@ -383,10 +384,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
383384
}
384385
}
385386
};
386-
let move_ty = format!("{:?}", move_place.ty(*self.body, self.infcx.tcx).ty,);
387387
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
388-
let is_option = move_ty.starts_with("std::option::Option");
389-
let is_result = move_ty.starts_with("std::result::Result");
388+
let def_id = match move_place.ty(*self.body, self.infcx.tcx).ty.kind {
389+
ty::Adt(self_def, _) => self_def.did,
390+
ty::Foreign(def_id)
391+
| ty::FnDef(def_id, _)
392+
| ty::Closure(def_id, _)
393+
| ty::Generator(def_id, ..)
394+
| ty::Opaque(def_id, _) => def_id,
395+
_ => return err,
396+
};
397+
let is_option =
398+
self.infcx.tcx.is_diagnostic_item(Symbol::intern("option_type"), def_id);
399+
let is_result =
400+
self.infcx.tcx.is_diagnostic_item(Symbol::intern("result_type"), def_id);
390401
if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) {
391402
err.span_suggestion(
392403
span,
@@ -397,6 +408,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
397408
format!("{}.as_ref()", snippet),
398409
Applicability::MaybeIncorrect,
399410
);
411+
} else if span.is_desugaring(DesugaringKind::ForLoop)
412+
&& self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id)
413+
{
414+
// FIXME: suggest for anything that implements `IntoIterator`.
415+
err.span_suggestion(
416+
span,
417+
"consider iterating over a slice of the `Vec<_>`'s content",
418+
format!("&{}", snippet),
419+
Applicability::MaybeIncorrect,
420+
);
400421
}
401422
}
402423
err
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct Foo {
5+
v: Vec<u32>,
6+
}
7+
8+
impl Foo {
9+
fn bar(&self) {
10+
for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
11+
}
12+
}
13+
}
14+
15+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
#![allow(dead_code)]
3+
4+
struct Foo {
5+
v: Vec<u32>,
6+
}
7+
8+
impl Foo {
9+
fn bar(&self) {
10+
for _ in self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
11+
}
12+
}
13+
}
14+
15+
fn main() {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0507]: cannot move out of `self.v` which is behind a shared reference
2+
--> $DIR/for-i-in-vec.rs:10:18
3+
|
4+
LL | for _ in self.v {
5+
| ^^^^^^
6+
| |
7+
| move occurs because `self.v` has type `std::vec::Vec<u32>`, which does not implement the `Copy` trait
8+
| help: consider iterating over a slice of the `Vec<_>`'s content: `&self.v`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0507`.

0 commit comments

Comments
 (0)