Skip to content

Tweak move error #94515

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 9, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 15 additions & 140 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -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[..])
179 changes: 174 additions & 5 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
//! 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,
};
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",
);
}
}
}
}
44 changes: 6 additions & 38 deletions compiler/rustc_borrowck/src/diagnostics/move_errors.rs
Original file line number Diff line number Diff line change
@@ -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",
);
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/test/ui/borrowck/borrowck-move-by-capture.stderr
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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

6 changes: 2 additions & 4 deletions src/test/ui/borrowck/issue-27282-mutation-in-guard.stderr
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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

11 changes: 10 additions & 1 deletion src/test/ui/error-codes/E0507.stderr
Original file line number Diff line number Diff line change
@@ -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

6 changes: 2 additions & 4 deletions src/test/ui/issues/issue-27282-move-ref-mut-into-guard.stderr
Original file line number Diff line number Diff line change
@@ -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
9 changes: 5 additions & 4 deletions src/test/ui/issues/issue-61108.stderr
Original file line number Diff line number Diff line change
@@ -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

9 changes: 5 additions & 4 deletions src/test/ui/issues/issue-64559.stderr
Original file line number Diff line number Diff line change
@@ -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

9 changes: 5 additions & 4 deletions src/test/ui/loops/issue-82916.stderr
Original file line number Diff line number Diff line change
@@ -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

5 changes: 1 addition & 4 deletions src/test/ui/moves/issue-46099-move-in-macro.stderr
Original file line number Diff line number Diff line change
@@ -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

10 changes: 6 additions & 4 deletions src/test/ui/moves/move-fn-self-receiver.stderr
Original file line number Diff line number Diff line change
@@ -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
5 changes: 1 addition & 4 deletions src/test/ui/moves/move-in-guard-2.stderr
Original file line number Diff line number Diff line change
@@ -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

6 changes: 2 additions & 4 deletions src/test/ui/nll/match-guards-always-borrow.stderr
Original file line number Diff line number Diff line change
@@ -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
9 changes: 5 additions & 4 deletions src/test/ui/suggestions/borrow-for-loop-head.stderr
Original file line number Diff line number Diff line change
@@ -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

31 changes: 25 additions & 6 deletions src/test/ui/suggestions/for-i-in-vec.stderr
Original file line number Diff line number Diff line change
@@ -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
|
note: this function takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
help: consider iterating over a slice of the `Vec<&u8>`'s content
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 {
| +
2 changes: 1 addition & 1 deletion src/test/ui/suggestions/option-content-move2.stderr
Original file line number Diff line number Diff line change
@@ -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