Skip to content

Commit 2c11c35

Browse files
committed
Explain move errors that occur due to method calls involving self
1 parent 754da88 commit 2c11c35

39 files changed

+697
-82
lines changed

src/librustc_ast_lowering/expr.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec;
99
use rustc_errors::struct_span_err;
1010
use rustc_hir as hir;
1111
use rustc_hir::def::Res;
12-
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
12+
use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned};
1313
use rustc_span::symbol::{sym, Ident, Symbol};
1414
use rustc_target::asm;
1515
use std::collections::hash_map::Entry;
@@ -25,6 +25,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
2525
}
2626

2727
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
28+
let mut span = e.span;
2829
ensure_sufficient_stack(|| {
2930
let kind = match e.kind {
3031
ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
@@ -53,6 +54,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
5354
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
5455
}
5556
ExprKind::Binary(binop, ref lhs, ref rhs) => {
57+
span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None);
5658
let binop = self.lower_binop(binop);
5759
let lhs = self.lower_expr(lhs);
5860
let rhs = self.lower_expr(rhs);
@@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
222224
hir::Expr {
223225
hir_id: self.lower_node_id(e.id),
224226
kind,
225-
span: e.span,
227+
span,
226228
attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
227229
}
228230
})
@@ -237,6 +239,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
237239
}
238240

239241
fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
242+
let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None);
240243
Spanned {
241244
node: match b.node {
242245
BinOpKind::Add => hir::BinOpKind::Add,
@@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
258261
BinOpKind::Ge => hir::BinOpKind::Ge,
259262
BinOpKind::Gt => hir::BinOpKind::Gt,
260263
},
261-
span: b.span,
264+
span,
262265
}
263266
}
264267

@@ -1360,9 +1363,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
13601363
body: &Block,
13611364
opt_label: Option<Label>,
13621365
) -> hir::Expr<'hir> {
1366+
let orig_head_span = head.span;
13631367
// expand <head>
13641368
let mut head = self.lower_expr_mut(head);
1365-
let desugared_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
1369+
let desugared_span = self.mark_span_with_reason(
1370+
DesugaringKind::ForLoop(ForLoopLoc::Head),
1371+
orig_head_span,
1372+
None,
1373+
);
13661374
head.span = desugared_span;
13671375

13681376
let iter = Ident::with_dummy_span(sym::iter);
@@ -1457,10 +1465,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
14571465
// `mut iter => { ... }`
14581466
let iter_arm = self.arm(iter_pat, loop_expr);
14591467

1468+
let into_iter_span = self.mark_span_with_reason(
1469+
DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
1470+
orig_head_span,
1471+
None,
1472+
);
1473+
14601474
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
14611475
let into_iter_expr = {
14621476
let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
1463-
self.expr_call_std_path(desugared_span, into_iter_path, arena_vec![self; head])
1477+
self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
14641478
};
14651479

14661480
let match_expr = self.arena.alloc(self.expr_match(

src/librustc_infer/infer/error_reporting/need_type_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
455455
let msg = if let Some(simple_ident) = pattern.simple_ident() {
456456
match pattern.span.desugaring_kind() {
457457
None => format!("consider giving `{}` {}", simple_ident, suffix),
458-
Some(DesugaringKind::ForLoop) => {
458+
Some(DesugaringKind::ForLoop(_)) => {
459459
"the element type for this iterator is not specified".to_string()
460460
}
461461
_ => format!("this needs {}", suffix),

src/librustc_middle/lint.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,9 @@ pub fn struct_lint_level<'s, 'd>(
339339
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
340340
let expn_data = span.ctxt().outer_expn_data();
341341
match expn_data.kind {
342-
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
342+
ExpnKind::Root
343+
| ExpnKind::Desugaring(DesugaringKind::ForLoop(_))
344+
| ExpnKind::Desugaring(DesugaringKind::Operator) => false,
343345
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
344346
ExpnKind::Macro(MacroKind::Bang, _) => {
345347
// Dummy span for the `def_site` means it's an external macro.

src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ use crate::borrow_check::{
2424
};
2525

2626
use super::{
27-
explain_borrow::BorrowExplanation, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
27+
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
28+
RegionNameSource, UseSpans,
2829
};
2930

3031
#[derive(Debug)]
@@ -150,13 +151,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
150151
format!("value moved{} here, in previous iteration of loop", move_msg),
151152
);
152153
} else {
153-
err.span_label(move_span, format!("value moved{} here", move_msg));
154-
move_spans.var_span_label(
155-
&mut err,
156-
format!("variable moved due to use{}", move_spans.describe()),
157-
);
154+
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } =
155+
move_spans
156+
{
157+
let place_name = self
158+
.describe_place(moved_place.as_ref())
159+
.map(|n| format!("`{}`", n))
160+
.unwrap_or_else(|| "value".to_owned());
161+
match kind {
162+
FnSelfUseKind::FnOnceCall => {
163+
err.span_label(
164+
fn_call_span,
165+
&format!("{} moved due to this call", place_name),
166+
);
167+
err.span_note(
168+
var_span,
169+
"this value implements `FnOnce`, which causes it to be moved when called",
170+
);
171+
}
172+
FnSelfUseKind::Operator { self_arg } => {
173+
err.span_label(
174+
fn_call_span,
175+
&format!("{} moved due to usage in operator", place_name),
176+
);
177+
if self.fn_self_span_reported.insert(fn_span) {
178+
err.span_note(
179+
self_arg.span,
180+
"calling this operator moves the left-hand side",
181+
);
182+
}
183+
}
184+
FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
185+
if implicit_into_iter {
186+
err.span_label(
187+
fn_call_span,
188+
&format!(
189+
"{} moved due to this implicit call to `.into_iter()`",
190+
place_name
191+
),
192+
);
193+
} else {
194+
err.span_label(
195+
fn_call_span,
196+
&format!("{} moved due to this method call", place_name),
197+
);
198+
}
199+
// Avoid pointing to the same function in multiple different
200+
// error messages
201+
if self.fn_self_span_reported.insert(self_arg.span) {
202+
err.span_note(
203+
self_arg.span,
204+
&format!("this function consumes the receiver `self` by taking ownership of it, which moves {}", place_name)
205+
);
206+
}
207+
}
208+
}
209+
} else {
210+
err.span_label(move_span, format!("value moved{} here", move_msg));
211+
move_spans.var_span_label(
212+
&mut err,
213+
format!("variable moved due to use{}", move_spans.describe()),
214+
);
215+
}
158216
}
159-
if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() {
217+
if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
160218
let sess = self.infcx.tcx.sess;
161219
if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
162220
err.span_suggestion(

src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
509509
// Used in a closure.
510510
(LaterUseKind::ClosureCapture, var_span)
511511
}
512-
UseSpans::OtherUse(span) => {
512+
UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => {
513513
let block = &self.body.basic_blocks()[location.block];
514514

515515
let kind = if let Some(&Statement {

0 commit comments

Comments
 (0)