Tweak move error

Point at method definition that causes type to be consumed.

Fix #94056.
This commit is contained in:
Esteban Kuber 2022-03-02 04:30:16 +00:00
parent 32cbc7630b
commit 98752776b8
21 changed files with 289 additions and 242 deletions

View File

@ -1,5 +1,5 @@
use either::Either;
use rustc_const_eval::util::{CallDesugaringKind, CallKind};
use rustc_const_eval::util::CallKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
@ -17,7 +17,7 @@ use rustc_middle::ty::{
};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::symbol::sym;
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_span::{BytePos, MultiSpan, Span};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::TraitEngineExt as _;
@ -195,144 +195,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
is_loop_move = true;
}
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
let place_name = self
.describe_place(moved_place.as_ref())
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "value".to_owned());
match kind {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this call{}",
place_name, partially_str, loop_message
),
);
err.span_note(
var_span,
"this value implements `FnOnce`, which causes it to be moved when called",
);
}
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to usage in operator{}",
place_name, partially_str, loop_message
),
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
// Check whether the source is accessible
if self
.infcx
.tcx
.sess
.source_map()
.span_to_snippet(self_arg.span)
.is_ok()
{
self_arg.span
} else {
fn_call_span
},
"calling this operator moves the left-hand side",
);
}
}
CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
let self_arg = self_arg.unwrap();
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this implicit call to `.into_iter()`{}",
place_name, partially_str, loop_message
),
);
let sess = self.infcx.tcx.sess;
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
// If we have a `&mut` ref, we need to reborrow.
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
// If we are in a loop this will be suggested later.
if !is_loop_move {
err.span_suggestion_verbose(
move_span.shrink_to_lo(),
&format!(
"consider creating a fresh reborrow of {} here",
self.describe_place(moved_place.as_ref())
.map(|n| format!("`{}`", n))
.unwrap_or_else(
|| "the mutable reference".to_string()
),
),
"&mut *".to_string(),
Applicability::MachineApplicable,
);
}
} else if let Ok(snippet) =
sess.source_map().span_to_snippet(move_span)
{
err.span_suggestion(
move_span,
"consider borrowing to avoid moving into the for loop",
format!("&{}", snippet),
Applicability::MaybeIncorrect,
);
}
} else {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this method call{}",
place_name, partially_str, loop_message
),
);
}
if is_option_or_result && maybe_reinitialized_locations.is_empty() {
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
"consider calling `.as_ref()` to borrow the type's contents",
"as_ref().".to_string(),
Applicability::MachineApplicable,
);
}
// Avoid pointing to the same function in multiple different
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span)
{
err.span_note(
self_arg.span,
&format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
);
}
}
// Other desugarings takes &self, which cannot cause a move
_ => unreachable!(),
}
} else {
err.span_label(
move_span,
format!("value {}moved{} here{}", partially_str, move_msg, loop_message),
);
// If the move error occurs due to a loop, don't show
// another message for the same span
if loop_message.is_empty() {
move_spans.var_span_label(
&mut err,
format!(
"variable {}moved due to use{}",
partially_str,
move_spans.describe()
),
"moved",
);
}
}
self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
Some(used_place),
partially_str,
loop_message,
move_msg,
is_loop_move,
maybe_reinitialized_locations.is_empty(),
);
if let (UseSpans::PatUse(span), []) =
(move_spans, &maybe_reinitialized_locations[..])

View File

@ -1,11 +1,12 @@
//! Borrow checker diagnostics.
use rustc_const_eval::util::call_kind;
use rustc_errors::Diagnostic;
use rustc_const_eval::util::{call_kind, CallDesugaringKind};
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_hir::GeneratorKind;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::{
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
@ -13,8 +14,9 @@ use rustc_middle::mir::{
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::{symbol::sym, Span};
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
@ -482,9 +484,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
BorrowedContentSource::DerefSharedRef
}
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime
/// name where required.
pub(super) fn get_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String {
@ -995,4 +995,173 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let span = self.body.source_info(borrow.reserve_location).span;
self.borrow_spans(span, borrow.reserve_location)
}
fn explain_captures(
&mut self,
err: &mut Diagnostic,
span: Span,
move_span: Span,
move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>,
used_place: Option<PlaceRef<'tcx>>,
partially_str: &str,
loop_message: &str,
move_msg: &str,
is_loop_move: bool,
maybe_reinitialized_locations_is_empty: bool,
) {
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
let place_name = self
.describe_place(moved_place.as_ref())
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "value".to_owned());
match kind {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this call{}",
place_name, partially_str, loop_message
),
);
err.span_note(
var_span,
"this value implements `FnOnce`, which causes it to be moved when called",
);
}
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to usage in operator{}",
place_name, partially_str, loop_message
),
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
// Check whether the source is accessible
if self
.infcx
.tcx
.sess
.source_map()
.span_to_snippet(self_arg.span)
.is_ok()
{
self_arg.span
} else {
fn_call_span
},
"calling this operator moves the left-hand side",
);
}
}
CallKind::Normal { self_arg, desugaring, is_option_or_result } => {
let self_arg = self_arg.unwrap();
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
type_known_to_meet_bound_modulo_regions(
&infcx,
self.param_env,
infcx.tcx.mk_imm_ref(
infcx.tcx.lifetimes.re_erased,
infcx.tcx.erase_regions(ty),
),
def_id,
DUMMY_SP,
)
}),
_ => false,
};
if suggest {
err.span_suggestion_verbose(
move_span.shrink_to_lo(),
&format!(
"consider iterating over a slice of the `{}`'s content to \
avoid moving into the `for` loop",
ty,
),
"&".to_string(),
Applicability::MaybeIncorrect,
);
}
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this implicit call to `.into_iter()`{}",
place_name, partially_str, loop_message
),
);
// If we have a `&mut` ref, we need to reborrow.
if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place
.map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind())
{
// If we are in a loop this will be suggested later.
if !is_loop_move {
err.span_suggestion_verbose(
move_span.shrink_to_lo(),
&format!(
"consider creating a fresh reborrow of {} here",
self.describe_place(moved_place.as_ref())
.map(|n| format!("`{}`", n))
.unwrap_or_else(|| "the mutable reference".to_string()),
),
"&mut *".to_string(),
Applicability::MachineApplicable,
);
}
}
} else {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this method call{}",
place_name, partially_str, loop_message
),
);
}
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(),
"consider calling `.as_ref()` to borrow the type's contents",
"as_ref().".to_string(),
Applicability::MachineApplicable,
);
}
// Avoid pointing to the same function in multiple different
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
err.span_note(
self_arg.span,
&format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
);
}
}
// Other desugarings takes &self, which cannot cause a move
_ => {}
}
} else {
if move_span != span || !loop_message.is_empty() {
err.span_label(
move_span,
format!("value {}moved{} here{}", partially_str, move_msg, loop_message),
);
}
// If the move error occurs due to a loop, don't show
// another message for the same span
if loop_message.is_empty() {
move_spans.var_span_label(
err,
format!("variable {}moved due to use{}", partially_str, move_spans.describe()),
"moved",
);
}
}
}
}

View File

@ -1,15 +1,12 @@
use rustc_const_eval::util::CallDesugaringKind;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty;
use rustc_mir_dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
};
use rustc_span::{sym, Span, DUMMY_SP};
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use rustc_span::{sym, Span};
use crate::diagnostics::{CallKind, UseSpans};
use crate::diagnostics::UseSpans;
use crate::prefixes::PrefixSet;
use crate::MirBorrowckCtxt;
@ -409,34 +406,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
".as_ref()".to_string(),
Applicability::MaybeIncorrect,
);
} else if let Some(UseSpans::FnSelfUse {
kind:
CallKind::Normal { desugaring: Some((CallDesugaringKind::ForLoopIntoIter, _)), .. },
..
}) = use_spans
{
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
type_known_to_meet_bound_modulo_regions(
&infcx,
self.param_env,
infcx
.tcx
.mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
def_id,
DUMMY_SP,
)
}),
_ => false,
};
if suggest {
err.span_suggestion_verbose(
span.shrink_to_lo(),
&format!("consider iterating over a slice of the `{}`'s content", ty),
"&".to_string(),
Applicability::MaybeIncorrect,
);
}
} else if let Some(use_spans) = use_spans {
self.explain_captures(
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
);
}
err
}
@ -491,11 +464,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), "");
use_spans.args_span_label(err, format!("move out of {} occurs here", place_desc));
use_spans.var_span_label(
err,
format!("move occurs due to use{}", use_spans.describe()),
"moved",
);
}
}
}

View File

@ -2,10 +2,8 @@ error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/borrowck-feature-nll-overrides-migrate.rs:22:18
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ ---
| | |
| | move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| move out of `foo` occurs here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard

View File

@ -2,10 +2,8 @@ error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/borrowck-feature-nll-overrides-migrate.rs:22:18
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ ---
| | |
| | move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| move out of `foo` occurs here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard

View File

@ -8,8 +8,8 @@ LL | let _g = to_fn_mut(|| {
LL | | let _h = to_fn_once(move || -> isize { *bar });
| | ^^^^^^^^^^^^^^^^ ----
| | | |
| | | variable moved due to use in closure
| | | move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
| | | move occurs due to use in closure
| | move out of `bar` occurs here
LL | | });
| |_____- captured by this `FnMut` closure

View File

@ -2,7 +2,16 @@ error[E0507]: cannot move out of an `Rc`
--> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:4:14
|
LL | let _x = Rc::new(vec![1, 2]).into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
| ^^^^^^^^^^^^^^^^^^^^-----------
| | |
| | value moved due to this method call
| move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -2,10 +2,8 @@ error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-mutation-in-guard.rs:6:18
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ ---
| | |
| | move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| move out of `foo` occurs here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard

View File

@ -6,10 +6,18 @@ LL | let y = vec![format!("World")];
LL | call(|| {
| __________-
LL | | y.into_iter();
| | ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
| | ^ ----------- `y` moved due to this method call
| | |
| | move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
LL | |
LL | | });
| |_____- captured by this `Fn` closure
|
note: this function takes ownership of the receiver `self`, which moves `y`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -2,7 +2,16 @@ error[E0507]: cannot move out of dereference of `Ref<'_, TheDarkKnight>`
--> $DIR/E0507.rs:12:5
|
LL | x.borrow().nothing_is_true();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
| ^^^^^^^^^^^-----------------
| | |
| | value moved due to this method call
| move occurs because value has type `TheDarkKnight`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves value
--> $DIR/E0507.rs:6:24
|
LL | fn nothing_is_true(self) {}
| ^^^^
error: aborting due to previous error

View File

@ -2,10 +2,8 @@ error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19
|
LL | if { (|| { let bar = foo; bar.take() })(); false } => {},
| ^^ ---
| | |
| | move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| move out of `foo` occurs here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard

View File

@ -4,10 +4,7 @@ error[E0382]: borrow of moved value: `bad_letters`
LL | let mut bad_letters = vec!['e', 't', 'o', 'i'];
| --------------- move occurs because `bad_letters` has type `Vec<char>`, which does not implement the `Copy` trait
LL | for l in bad_letters {
| -----------
| |
| `bad_letters` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&bad_letters`
| ----------- `bad_letters` moved due to this implicit call to `.into_iter()`
...
LL | bad_letters.push('s');
| ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
@ -17,6 +14,10 @@ note: this function takes ownership of the receiver `self`, which moves `bad_let
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<char>`'s content to avoid moving into the `for` loop
|
LL | for l in &bad_letters {
| +
error: aborting due to previous error

View File

@ -4,10 +4,7 @@ error[E0382]: use of moved value: `orig`
LL | let orig = vec![true];
| ---- move occurs because `orig` has type `Vec<bool>`, which does not implement the `Copy` trait
LL | for _val in orig {}
| ----
| |
| `orig` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&orig`
| ---- `orig` moved due to this implicit call to `.into_iter()`
LL | let _closure = || orig;
| ^^ ---- use occurs due to use in closure
| |
@ -18,6 +15,10 @@ note: this function takes ownership of the receiver `self`, which moves `orig`
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
|
LL | for _val in &orig {}
| +
error: aborting due to previous error

View File

@ -4,10 +4,7 @@ error[E0382]: use of moved value: `x`
LL | fn foo(x: Vec<S>) {
| - move occurs because `x` has type `Vec<S>`, which does not implement the `Copy` trait
LL | for y in x {
| -
| |
| `x` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&x`
| - `x` moved due to this implicit call to `.into_iter()`
...
LL | let z = x;
| ^ value used here after move
@ -17,6 +14,10 @@ note: this function takes ownership of the receiver `self`, which moves `x`
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<S>`'s content to avoid moving into the `for` loop
|
LL | for y in &x {
| +
error: aborting due to previous error

View File

@ -4,10 +4,7 @@ error[E0382]: use of moved value: `b`
LL | let b = Box::new(true);
| - move occurs because `b` has type `Box<bool>`, which does not implement the `Copy` trait
LL | test!({b});
| ^
| |
| value moved here
| value used here after move
| ^ value used here after move
error: aborting due to previous error

View File

@ -119,12 +119,14 @@ error[E0382]: use of moved value: `implicit_into_iter`
LL | let implicit_into_iter = vec![true];
| ------------------ move occurs because `implicit_into_iter` has type `Vec<bool>`, which does not implement the `Copy` trait
LL | for _val in implicit_into_iter {}
| ------------------
| |
| `implicit_into_iter` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&implicit_into_iter`
| ------------------ `implicit_into_iter` moved due to this implicit call to `.into_iter()`
LL | implicit_into_iter;
| ^^^^^^^^^^^^^^^^^^ value used here after move
|
help: consider iterating over a slice of the `Vec<bool>`'s content to avoid moving into the `for` loop
|
LL | for _val in &implicit_into_iter {}
| +
error[E0382]: use of moved value: `explicit_into_iter`
--> $DIR/move-fn-self-receiver.rs:67:5

View File

@ -5,10 +5,7 @@ LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (_, 2) if take(x) => (),
| ^
| |
| value moved here
| value used here after move
| ^ value used here after move
error: aborting due to previous error

View File

@ -2,10 +2,8 @@ error[E0507]: cannot move out of `foo` in pattern guard
--> $DIR/match-guards-always-borrow.rs:8:14
|
LL | (|| { let bar = foo; bar.take() })();
| ^^ ---
| | |
| | move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
| ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait
| |
| move out of `foo` occurs here
|
= note: variables bound in patterns cannot be moved from until after the end of the pattern guard

View File

@ -13,16 +13,17 @@ LL | let a = vec![1, 2, 3];
| - move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait
LL | for i in &a {
LL | for j in a {
| ^
| |
| `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
| help: consider borrowing to avoid moving into the for loop: `&a`
| ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
|
note: this function takes ownership of the receiver `self`, which moves `a`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<i32>`'s content to avoid moving into the `for` loop
|
LL | for j in &a {
| +
error: aborting due to 2 previous errors

View File

@ -2,9 +2,17 @@ error[E0507]: cannot move out of `self.v` which is behind a shared reference
--> $DIR/for-i-in-vec.rs:11:18
|
LL | for _ in self.v {
| ^^^^^^ move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
| ^^^^^^
| |
| `self.v` moved due to this implicit call to `.into_iter()`
| move occurs because `self.v` has type `Vec<u32>`, which does not implement the `Copy` trait
|
help: consider iterating over a slice of the `Vec<u32>`'s content
note: this function takes ownership of the receiver `self`, which moves `self.v`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<u32>`'s content to avoid moving into the `for` loop
|
LL | for _ in &self.v {
| +
@ -13,9 +21,12 @@ error[E0507]: cannot move out of `self.h` which is behind a shared reference
--> $DIR/for-i-in-vec.rs:13:18
|
LL | for _ in self.h {
| ^^^^^^ move occurs because `self.h` has type `HashMap<i32, i32>`, which does not implement the `Copy` trait
| ^^^^^^
| |
| `self.h` moved due to this implicit call to `.into_iter()`
| move occurs because `self.h` has type `HashMap<i32, i32>`, which does not implement the `Copy` trait
|
help: consider iterating over a slice of the `HashMap<i32, i32>`'s content
help: consider iterating over a slice of the `HashMap<i32, i32>`'s content to avoid moving into the `for` loop
|
LL | for _ in &self.h {
| +
@ -24,9 +35,17 @@ error[E0507]: cannot move out of a shared reference
--> $DIR/for-i-in-vec.rs:21:19
|
LL | for loader in *LOADERS {
| ^^^^^^^^ move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
| ^^^^^^^^
| |
| value moved due to this implicit call to `.into_iter()`
| move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
|
help: consider iterating over a slice of the `Vec<&u8>`'s content
note: this function takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid moving into the `for` loop
|
LL | for loader in &*LOADERS {
| +

View File

@ -12,8 +12,8 @@ LL | |
LL | | var = Some(NotCopyable);
| | ---
| | |
| | variable moved due to use in closure
| | move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
| | move occurs due to use in closure
LL | | }
LL | | });
| |_____- captured by this `FnMut` closure