Skip to content
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

Explain method-call move errors in loops #80324

Merged
merged 2 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
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
142 changes: 68 additions & 74 deletions compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,95 +151,88 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

let move_msg = if move_spans.for_closure() { " into closure" } else { "" };

let loop_message = if location == move_out.source || move_site.traversed_back_edge {
", in previous iteration of loop"
} else {
""
};

if location == move_out.source {
err.span_label(
span,
format!(
"value {}moved{} here, in previous iteration of loop",
partially_str, move_msg
),
);
is_loop_move = true;
} else if move_site.traversed_back_edge {
err.span_label(
move_span,
format!(
"value {}moved{} here, in previous iteration of loop",
partially_str, move_msg
),
);
} else {
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 {
FnSelfUseKind::FnOnceCall => {
}

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 {
FnSelfUseKind::FnOnceCall => {
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",
);
}
FnSelfUseKind::Operator { self_arg } => {
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(
self_arg.span,
"calling this operator moves the left-hand side",
);
}
}
FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
if implicit_into_iter {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this call",
place_name, partially_str
"{} {}moved due to this implicit call to `.into_iter()`{}",
place_name, partially_str, loop_message
),
);
err.span_note(
var_span,
"this value implements `FnOnce`, which causes it to be moved when called",
);
}
FnSelfUseKind::Operator { self_arg } => {
} else {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to usage in operator",
place_name, partially_str
"{} {}moved due to this method call{}",
place_name, partially_str, loop_message
),
);
if self.fn_self_span_reported.insert(fn_span) {
err.span_note(
self_arg.span,
"calling this operator moves the left-hand side",
);
}
}
FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
if implicit_into_iter {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this implicit call to `.into_iter()`",
place_name, partially_str
),
);
} else {
err.span_label(
fn_call_span,
&format!(
"{} {}moved due to this method call",
place_name, partially_str
),
);
}
// Avoid pointing to the same function in multiple different
// error messages
if self.fn_self_span_reported.insert(self_arg.span) {
err.span_note(
self_arg.span,
&format!("this function consumes the receiver `self` by taking ownership of it, which moves {}", place_name)
);
}
// Avoid pointing to the same function in multiple different
// error messages
if 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)
);
}
// Deref::deref takes &self, which cannot cause a move
FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
}
} else {
err.span_label(
move_span,
format!("value {}moved{} here", partially_str, move_msg),
);
// Deref::deref takes &self, which cannot cause a move
FnSelfUseKind::DerefCoercion { .. } => 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!(
Expand All @@ -250,6 +243,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
}

if let UseSpans::PatUse(span) = move_spans {
err.span_suggestion_verbose(
span.shrink_to_lo(),
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/codemap_tests/tab_3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ LL | {
LL | println!("{:?}", some_vec);
| ^^^^^^^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `some_vec`
note: this function takes ownership of the receiver `self`, which moves `some_vec`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-34721.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | };
LL | x.zero()
| ^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
note: this function takes ownership of the receiver `self`, which moves `x`
--> $DIR/issue-34721.rs:4:13
|
LL | fn zero(self) -> Self;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-61108.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ LL | for l in bad_letters {
LL | bad_letters.push('s');
| ^^^^^^^^^^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `bad_letters`
note: this function takes ownership of the receiver `self`, which moves `bad_letters`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-64559.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | let _closure = || orig;
| |
| value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `orig`
note: this function takes ownership of the receiver `self`, which moves `orig`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/moves/move-fn-self-receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ fn move_out(val: Container) {
let container = Container(vec![]);
for _val in container.custom_into_iter() {}
container; //~ ERROR use of moved

let foo2 = Foo;
loop {
foo2.use_self(); //~ ERROR use of moved
}
}

fn main() {}
23 changes: 16 additions & 7 deletions src/test/ui/moves/move-fn-self-receiver.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ LL | val.0.into_iter().next();
LL | val.0;
| ^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0`
note: this function takes ownership of the receiver `self`, which moves `val.0`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand All @@ -23,7 +23,7 @@ LL | foo.use_self();
LL | foo;
| ^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `foo`
note: this function takes ownership of the receiver `self`, which moves `foo`
--> $DIR/move-fn-self-receiver.rs:13:17
|
LL | fn use_self(self) {}
Expand All @@ -49,7 +49,7 @@ LL | boxed_foo.use_box_self();
LL | boxed_foo;
| ^^^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo`
note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
--> $DIR/move-fn-self-receiver.rs:14:21
|
LL | fn use_box_self(self: Box<Self>) {}
Expand All @@ -65,7 +65,7 @@ LL | pin_box_foo.use_pin_box_self();
LL | pin_box_foo;
| ^^^^^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `pin_box_foo`
note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
--> $DIR/move-fn-self-receiver.rs:15:25
|
LL | fn use_pin_box_self(self: Pin<Box<Self>>) {}
Expand All @@ -91,7 +91,7 @@ LL | rc_foo.use_rc_self();
LL | rc_foo;
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo`
note: this function takes ownership of the receiver `self`, which moves `rc_foo`
--> $DIR/move-fn-self-receiver.rs:16:20
|
LL | fn use_rc_self(self: Rc<Self>) {}
Expand Down Expand Up @@ -146,13 +146,22 @@ LL | for _val in container.custom_into_iter() {}
LL | container;
| ^^^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `container`
note: this function takes ownership of the receiver `self`, which moves `container`
--> $DIR/move-fn-self-receiver.rs:23:25
|
LL | fn custom_into_iter(self) -> impl Iterator<Item = bool> {
| ^^^^

error: aborting due to 11 previous errors
error[E0382]: use of moved value: `foo2`
--> $DIR/move-fn-self-receiver.rs:75:9
|
LL | let foo2 = Foo;
| ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait
LL | loop {
LL | foo2.use_self();
| ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop

error: aborting due to 12 previous errors

Some errors have detailed explanations: E0382, E0505.
For more information about an error, try `rustc --explain E0382`.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | consume(x.into_iter().next().unwrap());
LL | touch(&x[0]);
| ^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
note: this function takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/moves/moves-based-on-type-exprs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ LL | let _y = x.into_iter().next().unwrap();
LL | touch(&x);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
note: this function takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand All @@ -124,7 +124,7 @@ LL | let _y = [x.into_iter().next().unwrap(); 1];
LL | touch(&x);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
note: this function takes ownership of the receiver `self`, which moves `x`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
Expand Down
8 changes: 7 additions & 1 deletion src/test/ui/suggestions/borrow-for-loop-head.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ LL | for i in &a {
LL | for j in a {
| ^
| |
| value moved here, in previous iteration of loop
| `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`
|
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;
| ^^^^

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/unsized-locals/borrow-after-move.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ LL | y.foo();
LL | println!("{}", &y);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
note: this function takes ownership of the receiver `self`, which moves `y`
--> $DIR/borrow-after-move.rs:5:12
|
LL | fn foo(self) -> String;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/unsized-locals/double-move.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ LL | y.foo();
LL | y.foo();
| ^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
note: this function takes ownership of the receiver `self`, which moves `y`
--> $DIR/double-move.rs:5:12
|
LL | fn foo(self) -> String;
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/use/use-after-move-self-based-on-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | self.bar();
LL | return self.x;
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
note: this function takes ownership of the receiver `self`, which moves `self`
--> $DIR/use-after-move-self-based-on-type.rs:15:16
|
LL | pub fn bar(self) {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/use/use-after-move-self.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | self.bar();
LL | return *self.x;
| ^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
note: this function takes ownership of the receiver `self`, which moves `self`
--> $DIR/use-after-move-self.rs:13:16
|
LL | pub fn bar(self) {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/walk-struct-literal-with.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LL | let end = Mine{other_val:1, ..start.make_string_bar()};
LL | println!("{}", start.test);
| ^^^^^^^^^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `start`
note: this function takes ownership of the receiver `self`, which moves `start`
--> $DIR/walk-struct-literal-with.rs:7:28
|
LL | fn make_string_bar(mut self) -> Mine{
Expand Down