Explain move errors that occur due to method calls involving self

This is a re-attempt of #72389 (which was reverted in #73594)
Instead of using `ExpnKind::Desugaring` to represent operators, this PR
checks the lang item directly.
This commit is contained in:
Aaron Hill 2020-06-11 13:48:46 -04:00
parent 36ac08e264
commit fa6a61c689
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
38 changed files with 746 additions and 103 deletions

View File

@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_target::asm;
use std::collections::hash_map::Entry;
@ -1361,9 +1361,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Block,
opt_label: Option<Label>,
) -> hir::Expr<'hir> {
let orig_head_span = head.span;
// expand <head>
let mut head = self.lower_expr_mut(head);
let desugared_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
let desugared_span = self.mark_span_with_reason(
DesugaringKind::ForLoop(ForLoopLoc::Head),
orig_head_span,
None,
);
head.span = desugared_span;
let iter = Ident::with_dummy_span(sym::iter);
@ -1458,10 +1463,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `mut iter => { ... }`
let iter_arm = self.arm(iter_pat, loop_expr);
let into_iter_span = self.mark_span_with_reason(
DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
orig_head_span,
None,
);
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
self.expr_call_std_path(desugared_span, into_iter_path, arena_vec![self; head])
self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
};
let match_expr = self.arena.alloc(self.expr_match(

View File

@ -21,11 +21,26 @@ use rustc_span::Span;
use lazy_static::lazy_static;
pub enum LangItemGroup {
Op,
}
const NUM_GROUPS: usize = 1;
macro_rules! expand_group {
() => {
None
};
($group:expr) => {
Some($group)
};
}
// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! language_item_table {
(
$( $variant:ident, $name:expr, $method:ident, $target:expr; )*
$( $variant:ident $($group:expr)?, $name:expr, $method:ident, $target:expr; )*
) => {
enum_from_u32! {
@ -45,6 +60,13 @@ macro_rules! language_item_table {
$( $variant => $name, )*
}
}
pub fn group(self) -> Option<LangItemGroup> {
use LangItemGroup::*;
match self {
$( $variant => expand_group!($($group)*), )*
}
}
}
#[derive(HashStable_Generic)]
@ -54,6 +76,9 @@ macro_rules! language_item_table {
pub items: Vec<Option<DefId>>,
/// Lang items that were not found during collection.
pub missing: Vec<LangItem>,
/// Mapping from `LangItemGroup` discriminants to all
/// `DefId`s of lang items in that group.
pub groups: [Vec<DefId>; NUM_GROUPS],
}
impl LanguageItems {
@ -64,6 +89,7 @@ macro_rules! language_item_table {
Self {
items: vec![$(init_none($variant)),*],
missing: Vec::new(),
groups: [vec![]; NUM_GROUPS],
}
}
@ -79,6 +105,10 @@ macro_rules! language_item_table {
self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
}
pub fn group(&self, group: LangItemGroup) -> &[DefId] {
self.groups[group as usize].as_ref()
}
$(
/// Returns the corresponding `DefId` for the lang item
#[doc = $name]
@ -171,30 +201,30 @@ language_item_table! {
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait, Target::Trait;
DispatchFromDynTraitLangItem,"dispatch_from_dyn", dispatch_from_dyn_trait, Target::Trait;
AddTraitLangItem, "add", add_trait, Target::Trait;
SubTraitLangItem, "sub", sub_trait, Target::Trait;
MulTraitLangItem, "mul", mul_trait, Target::Trait;
DivTraitLangItem, "div", div_trait, Target::Trait;
RemTraitLangItem, "rem", rem_trait, Target::Trait;
NegTraitLangItem, "neg", neg_trait, Target::Trait;
NotTraitLangItem, "not", not_trait, Target::Trait;
BitXorTraitLangItem, "bitxor", bitxor_trait, Target::Trait;
BitAndTraitLangItem, "bitand", bitand_trait, Target::Trait;
BitOrTraitLangItem, "bitor", bitor_trait, Target::Trait;
ShlTraitLangItem, "shl", shl_trait, Target::Trait;
ShrTraitLangItem, "shr", shr_trait, Target::Trait;
AddAssignTraitLangItem, "add_assign", add_assign_trait, Target::Trait;
SubAssignTraitLangItem, "sub_assign", sub_assign_trait, Target::Trait;
MulAssignTraitLangItem, "mul_assign", mul_assign_trait, Target::Trait;
DivAssignTraitLangItem, "div_assign", div_assign_trait, Target::Trait;
RemAssignTraitLangItem, "rem_assign", rem_assign_trait, Target::Trait;
BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait, Target::Trait;
BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait, Target::Trait;
BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait, Target::Trait;
ShlAssignTraitLangItem, "shl_assign", shl_assign_trait, Target::Trait;
ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait;
IndexTraitLangItem, "index", index_trait, Target::Trait;
IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait;
AddTraitLangItem(Op), "add", add_trait, Target::Trait;
SubTraitLangItem(Op), "sub", sub_trait, Target::Trait;
MulTraitLangItem(Op), "mul", mul_trait, Target::Trait;
DivTraitLangItem(Op), "div", div_trait, Target::Trait;
RemTraitLangItem(Op), "rem", rem_trait, Target::Trait;
NegTraitLangItem(Op), "neg", neg_trait, Target::Trait;
NotTraitLangItem(Op), "not", not_trait, Target::Trait;
BitXorTraitLangItem(Op), "bitxor", bitxor_trait, Target::Trait;
BitAndTraitLangItem(Op), "bitand", bitand_trait, Target::Trait;
BitOrTraitLangItem(Op), "bitor", bitor_trait, Target::Trait;
ShlTraitLangItem(Op), "shl", shl_trait, Target::Trait;
ShrTraitLangItem(Op), "shr", shr_trait, Target::Trait;
AddAssignTraitLangItem(Op), "add_assign", add_assign_trait, Target::Trait;
SubAssignTraitLangItem(Op), "sub_assign", sub_assign_trait, Target::Trait;
MulAssignTraitLangItem(Op), "mul_assign", mul_assign_trait, Target::Trait;
DivAssignTraitLangItem(Op), "div_assign", div_assign_trait, Target::Trait;
RemAssignTraitLangItem(Op), "rem_assign", rem_assign_trait, Target::Trait;
BitXorAssignTraitLangItem(Op),"bitxor_assign", bitxor_assign_trait, Target::Trait;
BitAndAssignTraitLangItem(Op),"bitand_assign", bitand_assign_trait, Target::Trait;
BitOrAssignTraitLangItem(Op),"bitor_assign", bitor_assign_trait, Target::Trait;
ShlAssignTraitLangItem(Op), "shl_assign", shl_assign_trait, Target::Trait;
ShrAssignTraitLangItem(Op), "shr_assign", shr_assign_trait, Target::Trait;
IndexTraitLangItem(Op), "index", index_trait, Target::Trait;
IndexMutTraitLangItem(Op), "index_mut", index_mut_trait, Target::Trait;
UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct;
VaListTypeLangItem, "va_list", va_list, Target::Struct;

View File

@ -468,7 +468,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let msg = if let Some(simple_ident) = pattern.simple_ident() {
match pattern.span.desugaring_kind() {
None => format!("consider giving `{}` {}", simple_ident, suffix),
Some(DesugaringKind::ForLoop) => {
Some(DesugaringKind::ForLoop(_)) => {
"the element type for this iterator is not specified".to_string()
}
_ => format!("this needs {}", suffix),

View File

@ -339,7 +339,7 @@ pub fn struct_lint_level<'s, 'd>(
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let expn_data = span.ctxt().outer_expn_data();
match expn_data.kind {
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop(_)) => false,
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.

View File

@ -24,7 +24,8 @@ use crate::borrow_check::{
};
use super::{
explain_borrow::BorrowExplanation, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
RegionNameSource, UseSpans,
};
#[derive(Debug)]
@ -150,11 +151,68 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
format!("value moved{} here, in previous iteration of loop", move_msg),
);
} else {
err.span_label(move_span, format!("value moved{} here", move_msg));
move_spans.var_span_label(
&mut err,
format!("variable moved due to use{}", move_spans.describe()),
);
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),
);
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),
);
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
),
);
} else {
err.span_label(
fn_call_span,
&format!("{} moved due to this method call", 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 consumes the receiver `self` by taking ownership of it, which moves {}", place_name)
);
}
}
}
} else {
err.span_label(move_span, format!("value moved{} here", move_msg));
move_spans.var_span_label(
&mut err,
format!("variable moved due to use{}", move_spans.describe()),
);
}
}
if let UseSpans::PatUse(span) = move_spans {
err.span_suggestion_verbose(
@ -170,7 +228,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() {
if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
let sess = self.infcx.tcx.sess;
if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
err.span_suggestion(

View File

@ -509,7 +509,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Used in a closure.
(LaterUseKind::ClosureCapture, var_span)
}
UseSpans::PatUse(span) | UseSpans::OtherUse(span) => {
UseSpans::PatUse(span)
| UseSpans::OtherUse(span)
| UseSpans::FnSelfUse { var_span: span, .. } => {
let block = &self.body.basic_blocks()[location.block];
let kind = if let Some(&Statement {

View File

@ -4,6 +4,7 @@ use rustc_errors::DiagnosticBuilder;
use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItemGroup;
use rustc_hir::GeneratorKind;
use rustc_middle::mir::{
AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
@ -11,7 +12,11 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_span::{symbol::sym, Span};
use rustc_span::{
hygiene::{DesugaringKind, ForLoopLoc},
symbol::sym,
Span,
};
use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData;
@ -33,6 +38,7 @@ crate use mutability_errors::AccessKind;
crate use outlives_suggestion::OutlivesSuggestionBuilder;
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
crate use region_name::{RegionName, RegionNameSource};
use rustc_span::symbol::Ident;
pub(super) struct IncludingDowncast(pub(super) bool);
@ -529,30 +535,52 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
// The span(s) associated to a use of a place.
/// The span(s) associated to a use of a place.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(super) enum UseSpans {
// The access is caused by capturing a variable for a closure.
/// The access is caused by capturing a variable for a closure.
ClosureUse {
// This is true if the captured variable was from a generator.
/// This is true if the captured variable was from a generator.
generator_kind: Option<GeneratorKind>,
// The span of the args of the closure, including the `move` keyword if
// it's present.
/// The span of the args of the closure, including the `move` keyword if
/// it's present.
args_span: Span,
// The span of the first use of the captured variable inside the closure.
/// The span of the first use of the captured variable inside the closure.
var_span: Span,
},
/// The access is caused by using a variable as the receiver of a method
/// that takes 'self'
FnSelfUse {
/// The span of the variable being moved
var_span: Span,
/// The span of the method call on the variable
fn_call_span: Span,
/// The definition span of the method being called
fn_span: Span,
kind: FnSelfUseKind,
},
/// This access is caused by a `match` or `if let` pattern.
PatUse(Span),
/// This access has a single span associated to it: common case.
OtherUse(Span),
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(super) enum FnSelfUseKind {
/// A normal method call of the form `receiver.foo(a, b, c)`
Normal { self_arg: Ident, implicit_into_iter: bool },
/// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
FnOnceCall,
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
Operator { self_arg: Ident },
}
impl UseSpans {
pub(super) fn args_or_use(self) -> Span {
match self {
UseSpans::ClosureUse { args_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::FnSelfUse { var_span: span, .. }
| UseSpans::OtherUse(span) => span,
}
}
@ -561,6 +589,7 @@ impl UseSpans {
match self {
UseSpans::ClosureUse { var_span: span, .. }
| UseSpans::PatUse(span)
| UseSpans::FnSelfUse { var_span: span, .. }
| UseSpans::OtherUse(span) => span,
}
}
@ -631,6 +660,7 @@ impl UseSpans {
match self {
closure @ UseSpans::ClosureUse { .. } => closure,
UseSpans::PatUse(_) | UseSpans::OtherUse(_) => if_other(),
fn_self @ UseSpans::FnSelfUse { .. } => fn_self,
}
}
}
@ -733,25 +763,112 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
let def_id = match kind {
match kind {
box AggregateKind::Closure(def_id, _)
| box AggregateKind::Generator(def_id, _, _) => def_id,
_ => return OtherUse(stmt.source_info.span),
};
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
if let Some((args_span, generator_kind, var_span)) =
self.closure_span(*def_id, moved_place, places)
{
return ClosureUse { generator_kind, args_span, var_span };
| box AggregateKind::Generator(def_id, _, _) => {
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
if let Some((args_span, generator_kind, var_span)) =
self.closure_span(*def_id, moved_place, places)
{
return ClosureUse { generator_kind, args_span, var_span };
}
}
_ => {}
}
}
if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
PatUse(stmt.source_info.span)
} else {
OtherUse(stmt.source_info.span)
let normal_ret =
if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
PatUse(stmt.source_info.span)
} else {
OtherUse(stmt.source_info.span)
};
// We are trying to find MIR of the form:
// ```
// _temp = _moved_val;
// ...
// FnSelfCall(_temp, ...)
// ```
//
// where `_moved_val` is the place we generated the move error for,
// `_temp` is some other local, and `FnSelfCall` is a function
// that has a `self` parameter.
let target_temp = match stmt.kind {
StatementKind::Assign(box (temp, _)) if temp.as_local().is_some() => {
temp.as_local().unwrap()
}
_ => return normal_ret,
};
debug!("move_spans: target_temp = {:?}", target_temp);
if let Some(Terminator {
kind: TerminatorKind::Call { func, args, fn_span, from_hir_call, .. },
..
}) = &self.body[location.block].terminator
{
let mut method_did = None;
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
if let ty::FnDef(def_id, _) = ty.kind {
debug!("move_spans: fn = {:?}", def_id);
if let Some(ty::AssocItem { fn_has_self_parameter, .. }) =
self.infcx.tcx.opt_associated_item(def_id)
{
if *fn_has_self_parameter {
method_did = Some(def_id);
}
}
}
}
let tcx = self.infcx.tcx;
let method_did = if let Some(did) = method_did { did } else { return normal_ret };
if let [Operand::Move(self_place), ..] = **args {
if self_place.as_local() == Some(target_temp) {
let parent = tcx.parent(method_did);
let is_fn_once = parent == tcx.lang_items().fn_once_trait();
let is_operator = !from_hir_call
&& parent.map_or(false, |p| {
tcx.lang_items().group(LangItemGroup::Op).contains(&p)
});
let fn_call_span = *fn_span;
let self_arg = tcx.fn_arg_names(method_did)[0];
let kind = if is_fn_once {
FnSelfUseKind::FnOnceCall
} else if is_operator {
FnSelfUseKind::Operator { self_arg }
} else {
debug!(
"move_spans: method_did={:?}, fn_call_span={:?}",
method_did, fn_call_span
);
let implicit_into_iter = matches!(
fn_call_span.desugaring_kind(),
Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
);
FnSelfUseKind::Normal { self_arg, implicit_into_iter }
};
return FnSelfUse {
var_span: stmt.source_info.span,
fn_call_span,
fn_span: self
.infcx
.tcx
.sess
.source_map()
.guess_head_span(self.infcx.tcx.def_span(method_did)),
kind,
};
}
}
}
return normal_ret;
}
/// Finds the span of arguments of a closure (within `maybe_closure_span`)

View File

@ -408,7 +408,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
format!("{}.as_ref()", snippet),
Applicability::MaybeIncorrect,
);
} else if span.is_desugaring(DesugaringKind::ForLoop)
} else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_)))
&& self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id)
{
// FIXME: suggest for anything that implements `IntoIterator`.

View File

@ -365,7 +365,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
match opt_desugaring_kind {
// on for loops, RHS points to the iterator part
Some(DesugaringKind::ForLoop) => Some((
Some(DesugaringKind::ForLoop(_)) => Some((
false,
opt_assignment_rhs_span.unwrap(),
format!(

View File

@ -278,6 +278,7 @@ fn do_mir_borrowck<'a, 'tcx>(
move_data: &move_data,
location_table: &LocationTable::new(promoted_body),
movable_generator,
fn_self_span_reported: Default::default(),
locals_are_invalidated_at_exit,
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
@ -311,6 +312,7 @@ fn do_mir_borrowck<'a, 'tcx>(
location_table,
movable_generator,
locals_are_invalidated_at_exit,
fn_self_span_reported: Default::default(),
access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(),
reservation_warnings: Default::default(),
@ -487,6 +489,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
// but it is currently inconvenient to track down the `BorrowIndex`
// at the time we detect and report a reservation error.
reservation_error_reported: FxHashSet<Place<'tcx>>,
/// This fields keeps track of the `Span`s that we have
/// used to report extra information for `FnSelfUse`, to avoid
/// unnecessarily verbose errors.
fn_self_span_reported: FxHashSet<Span>,
/// Migration warnings to be reported for #56254. We delay reporting these
/// so that we can suppress the warning if there's a corresponding error
/// for the activation of the borrow.

View File

@ -506,6 +506,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// This is basically `force_bits`.
let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok());
if r_bits.map_or(false, |b| b >= left_size.bits() as u128) {
debug!("check_binary_op: reporting assert for {:?}", source_info);
self.report_assert_as_lint(
lint::builtin::ARITHMETIC_OVERFLOW,
source_info,

View File

@ -102,7 +102,8 @@ impl LanguageItemCollector<'tcx> {
// Check for duplicates.
if let Some(original_def_id) = self.items.items[item_index] {
if original_def_id != item_def_id {
let name = LangItem::from_u32(item_index as u32).unwrap().name();
let lang_item = LangItem::from_u32(item_index as u32).unwrap();
let name = lang_item.name();
let mut err = match self.tcx.hir().span_if_local(item_def_id) {
Some(span) => struct_span_err!(
self.tcx.sess,
@ -152,6 +153,9 @@ impl LanguageItemCollector<'tcx> {
// Matched.
self.items.items[item_index] = Some(item_def_id);
if let Some(group) = LangItem::from_u32(item_index as u32).unwrap().group() {
self.items.groups[group as usize].push(item_def_id);
}
}
}

View File

@ -822,7 +822,14 @@ pub enum DesugaringKind {
OpaqueTy,
Async,
Await,
ForLoop,
ForLoop(ForLoopLoc),
}
/// A location in the desugaring of a `for` loop
#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
pub enum ForLoopLoc {
Head,
IntoIter,
}
impl DesugaringKind {
@ -835,7 +842,7 @@ impl DesugaringKind {
DesugaringKind::QuestionMark => "operator `?`",
DesugaringKind::TryBlock => "`try` block",
DesugaringKind::OpaqueTy => "`impl Trait`",
DesugaringKind::ForLoop => "`for` loop",
DesugaringKind::ForLoop(_) => "`for` loop",
}
}
}

View File

@ -30,8 +30,9 @@ use source_map::SourceMap;
pub mod edition;
use edition::Edition;
pub mod hygiene;
pub use hygiene::SyntaxContext;
use hygiene::Transparency;
pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext};
pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind};
pub mod def_id;
use def_id::{CrateNum, DefId, LOCAL_CRATE};
mod span_encoding;

View File

@ -4,10 +4,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs + rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn add(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -35,10 +40,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs - rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn sub(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -66,10 +76,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs * rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn mul(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -97,10 +112,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs / rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn div(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -128,10 +148,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs % rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn rem(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -159,10 +184,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs & rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn bitand(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -190,10 +220,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs | rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn bitor(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -221,10 +256,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs ^ rhs;
| --- value moved here
| --------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn bitxor(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -252,10 +292,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs << rhs;
| --- value moved here
| ---------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn shl(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@ -283,10 +328,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
| --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs >> rhs;
| --- value moved here
| ---------- `lhs` moved due to usage in operator
LL | drop(lhs);
| ^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn shr(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {

View File

@ -1,14 +1,21 @@
error[E0382]: use of moved value: `x`
--> $DIR/binop-move-semantics.rs:8:5
|
LL | fn double_move<T: Add<Output=()>>(x: T) {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | x
| - value moved here
LL | +
LL | x;
| ^ value used here after move
LL | fn double_move<T: Add<Output=()>>(x: T) {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | / x
LL | | +
LL | | x;
| | ^
| | |
| |_____value used here after move
| `x` moved due to usage in operator
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn add(self, rhs: Rhs) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {

View File

@ -22,10 +22,15 @@ error[E0382]: use of moved value: `f`
LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
| - move occurs because `f` has type `F`, which does not implement the `Copy` trait
LL | f(1, 2);
| - value moved here
| ------- `f` moved due to this call
LL | f(1, 2);
| ^ value used here after move
|
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/borrowck-unboxed-closures.rs:11:5
|
LL | f(1, 2);
| ^
help: consider further restricting this bound
|
LL | fn c<F:FnOnce(isize, isize) -> isize + Copy>(f: F) {

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `debug_dump_dict`
--> $DIR/issue-42065.rs:11:5
|
LL | debug_dump_dict();
| --------------- value moved here
| ----------------- `debug_dump_dict` moved due to this call
LL | debug_dump_dict();
| ^^^^^^^^^^^^^^^ value used here after move
|
@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `di
|
LL | for (key, value) in dict {
| ^^^^
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/issue-42065.rs:10:5
|
LL | debug_dump_dict();
| ^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -4,10 +4,16 @@ error[E0382]: borrow of moved value: `some_vec`
LL | let some_vec = vec!["hi"];
| -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
LL | some_vec.into_iter();
| -------- value moved here
| ----------- `some_vec` moved due to this method call
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`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -2,10 +2,15 @@ error[E0382]: use of moved value: `f`
--> $DIR/issue-12127.rs:11:9
|
LL | f();
| - value moved here
| --- `f` moved due to this call
LL | f();
| ^ value used here after move
|
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/issue-12127.rs:10:9
|
LL | f();
| ^
= note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:41 x:std::boxed::Box<isize>]`, which does not implement the `Copy` trait
error: aborting due to previous error

View File

@ -3,4 +3,5 @@ use std::collections::HashMap;
fn main() {
for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
//~^ ERROR type mismatch
//~| ERROR type mismatch
}

View File

@ -17,6 +17,16 @@ LL | for _ in HashMap::new().iter().cloned() {}
found reference `&_`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
error: aborting due to 2 previous errors
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
--> $DIR/issue-33941.rs:4:14
|
LL | for _ in HashMap::new().iter().cloned() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
|
= note: expected tuple `(&_, &_)`
found reference `&_`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0271`.

View File

@ -5,14 +5,19 @@ LL | pub fn baz<T: Foo>(x: T) -> T {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | if 0 == 1 {
LL | bar::bar(x.zero())
| - value moved here
| ------ `x` moved due to this method call
LL | } else {
LL | x.zero()
| - value moved here
| ------ `x` moved due to this method call
LL | };
LL | x.zero()
| ^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
--> $DIR/issue-34721.rs:4:13
|
LL | fn zero(self) -> Self;
| ^^^^
help: consider further restricting this bound
|
LL | pub fn baz<T: Foo + Copy>(x: T) -> T {

View File

@ -6,11 +6,17 @@ LL | let mut bad_letters = vec!['e', 't', 'o', 'i'];
LL | for l in bad_letters {
| -----------
| |
| value moved here
| `bad_letters` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&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`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -6,12 +6,18 @@ LL | let orig = vec![true];
LL | for _val in orig {}
| ----
| |
| value moved here
| `orig` moved due to this implicit call to `.into_iter()`
| help: consider borrowing to avoid moving into the for loop: `&orig`
LL | let _closure = || orig;
| ^^ ---- use occurs due to use in closure
| |
| value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `orig`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -0,0 +1,74 @@
use std::pin::Pin;
use std::rc::Rc;
use std::ops::Add;
struct Foo;
impl Add for Foo {
type Output = ();
fn add(self, _rhs: Self) -> () {}
}
impl Foo {
fn use_self(self) {}
fn use_box_self(self: Box<Self>) {}
fn use_pin_box_self(self: Pin<Box<Self>>) {}
fn use_rc_self(self: Rc<Self>) {}
fn use_mut_self(&mut self) -> &mut Self { self }
}
struct Container(Vec<bool>);
impl Container {
fn custom_into_iter(self) -> impl Iterator<Item = bool> {
self.0.into_iter()
}
}
fn move_out(val: Container) {
val.0.into_iter().next();
val.0; //~ ERROR use of moved
let foo = Foo;
foo.use_self();
foo; //~ ERROR use of moved
let second_foo = Foo;
second_foo.use_self();
second_foo; //~ ERROR use of moved
let boxed_foo = Box::new(Foo);
boxed_foo.use_box_self();
boxed_foo; //~ ERROR use of moved
let pin_box_foo = Box::pin(Foo);
pin_box_foo.use_pin_box_self();
pin_box_foo; //~ ERROR use of moved
let mut mut_foo = Foo;
let ret = mut_foo.use_mut_self();
mut_foo; //~ ERROR cannot move out
ret;
let rc_foo = Rc::new(Foo);
rc_foo.use_rc_self();
rc_foo; //~ ERROR use of moved
let foo_add = Foo;
foo_add + Foo;
foo_add; //~ ERROR use of moved
let implicit_into_iter = vec![true];
for _val in implicit_into_iter {}
implicit_into_iter; //~ ERROR use of moved
let explicit_into_iter = vec![true];
for _val in explicit_into_iter.into_iter() {}
explicit_into_iter; //~ ERROR use of moved
let container = Container(vec![]);
for _val in container.custom_into_iter() {}
container; //~ ERROR use of moved
}
fn main() {}

View File

@ -0,0 +1,158 @@
error[E0382]: use of moved value: `val.0`
--> $DIR/move-fn-self-receiver.rs:30:5
|
LL | val.0.into_iter().next();
| ----------- `val.0` moved due to this method call
LL | val.0;
| ^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
= note: move occurs because `val.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo`
--> $DIR/move-fn-self-receiver.rs:34:5
|
LL | let foo = Foo;
| --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
LL | foo.use_self();
| ---------- `foo` moved due to this method call
LL | foo;
| ^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `foo`
--> $DIR/move-fn-self-receiver.rs:13:17
|
LL | fn use_self(self) {}
| ^^^^
error[E0382]: use of moved value: `second_foo`
--> $DIR/move-fn-self-receiver.rs:38:5
|
LL | let second_foo = Foo;
| ---------- move occurs because `second_foo` has type `Foo`, which does not implement the `Copy` trait
LL | second_foo.use_self();
| ---------- `second_foo` moved due to this method call
LL | second_foo;
| ^^^^^^^^^^ value used here after move
error[E0382]: use of moved value: `boxed_foo`
--> $DIR/move-fn-self-receiver.rs:42:5
|
LL | let boxed_foo = Box::new(Foo);
| --------- move occurs because `boxed_foo` has type `std::boxed::Box<Foo>`, which does not implement the `Copy` trait
LL | boxed_foo.use_box_self();
| -------------- `boxed_foo` moved due to this method call
LL | boxed_foo;
| ^^^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo`
--> $DIR/move-fn-self-receiver.rs:14:21
|
LL | fn use_box_self(self: Box<Self>) {}
| ^^^^
error[E0382]: use of moved value: `pin_box_foo`
--> $DIR/move-fn-self-receiver.rs:46:5
|
LL | let pin_box_foo = Box::pin(Foo);
| ----------- move occurs because `pin_box_foo` has type `std::pin::Pin<std::boxed::Box<Foo>>`, which does not implement the `Copy` trait
LL | pin_box_foo.use_pin_box_self();
| ------------------ `pin_box_foo` moved due to this method call
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`
--> $DIR/move-fn-self-receiver.rs:15:25
|
LL | fn use_pin_box_self(self: Pin<Box<Self>>) {}
| ^^^^
error[E0505]: cannot move out of `mut_foo` because it is borrowed
--> $DIR/move-fn-self-receiver.rs:50:5
|
LL | let ret = mut_foo.use_mut_self();
| ------- borrow of `mut_foo` occurs here
LL | mut_foo;
| ^^^^^^^ move out of `mut_foo` occurs here
LL | ret;
| --- borrow later used here
error[E0382]: use of moved value: `rc_foo`
--> $DIR/move-fn-self-receiver.rs:55:5
|
LL | let rc_foo = Rc::new(Foo);
| ------ move occurs because `rc_foo` has type `std::rc::Rc<Foo>`, which does not implement the `Copy` trait
LL | rc_foo.use_rc_self();
| ------------- `rc_foo` moved due to this method call
LL | rc_foo;
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo`
--> $DIR/move-fn-self-receiver.rs:16:20
|
LL | fn use_rc_self(self: Rc<Self>) {}
| ^^^^
error[E0382]: use of moved value: `foo_add`
--> $DIR/move-fn-self-receiver.rs:59:5
|
LL | let foo_add = Foo;
| ------- move occurs because `foo_add` has type `Foo`, which does not implement the `Copy` trait
LL | foo_add + Foo;
| ------------- `foo_add` moved due to usage in operator
LL | foo_add;
| ^^^^^^^ value used here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/arith.rs:LL:COL
|
LL | fn add(self, rhs: Rhs) -> Self::Output;
| ^^^^
error[E0382]: use of moved value: `implicit_into_iter`
--> $DIR/move-fn-self-receiver.rs:63:5
|
LL | let implicit_into_iter = vec![true];
| ------------------ move occurs because `implicit_into_iter` has type `std::vec::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`
LL | implicit_into_iter;
| ^^^^^^^^^^^^^^^^^^ value used here after move
error[E0382]: use of moved value: `explicit_into_iter`
--> $DIR/move-fn-self-receiver.rs:67:5
|
LL | let explicit_into_iter = vec![true];
| ------------------ move occurs because `explicit_into_iter` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
LL | for _val in explicit_into_iter.into_iter() {}
| ----------- `explicit_into_iter` moved due to this method call
LL | explicit_into_iter;
| ^^^^^^^^^^^^^^^^^^ value used here after move
error[E0382]: use of moved value: `container`
--> $DIR/move-fn-self-receiver.rs:71:5
|
LL | let container = Container(vec![]);
| --------- move occurs because `container` has type `Container`, which does not implement the `Copy` trait
LL | for _val in container.custom_into_iter() {}
| ------------------ `container` moved due to this method call
LL | container;
| ^^^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, 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
Some errors have detailed explanations: E0382, E0505.
For more information about an error, try `rustc --explain E0382`.

View File

@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `x`
LL | let x = vec!["hi".to_string()];
| - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
LL | consume(x.into_iter().next().unwrap());
| - value moved here
| ----------- `x` moved due to this method call
LL | touch(&x[0]);
| ^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to previous error

View File

@ -104,9 +104,15 @@ error[E0382]: borrow of moved value: `x`
LL | let x = vec!["hi".to_string()];
| - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
LL | let _y = x.into_iter().next().unwrap();
| - value moved here
| ----------- `x` moved due to this method call
LL | touch(&x);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error[E0382]: borrow of moved value: `x`
--> $DIR/moves-based-on-type-exprs.rs:83:11
@ -114,9 +120,15 @@ error[E0382]: borrow of moved value: `x`
LL | let x = vec!["hi".to_string()];
| - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
LL | let _y = [x.into_iter().next().unwrap(); 1];
| - value moved here
| ----------- `x` moved due to this method call
LL | touch(&x);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
--> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
|
LL | fn into_iter(self) -> Self::IntoIter;
| ^^^^
error: aborting due to 11 previous errors

View File

@ -4,10 +4,15 @@ error[E0382]: use of moved value: `blk`
LL | fn foo<F:FnOnce()>(blk: F) {
| --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
LL | blk();
| --- value moved here
| ----- `blk` moved due to this call
LL | blk();
| ^^^ value used here after move
|
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/once-cant-call-twice-on-heap.rs:8:5
|
LL | blk();
| ^^^
help: consider further restricting this bound
|
LL | fn foo<F:FnOnce() + Copy>(blk: F) {

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
--> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5
|
LL | tick();
| ---- value moved here
| ------ `tick` moved due to this call
LL | tick();
| ^^^^ value used here after move
|
@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `co
|
LL | let tick = || mem::drop(counter);
| ^^^^^^^
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:9:5
|
LL | tick();
| ^^^^
error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
--> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5
|
LL | tick();
| ---- value moved here
| ------ `tick` moved due to this call
LL | tick();
| ^^^^ value used here after move
|
@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `co
|
LL | let tick = move || mem::drop(counter);
| ^^^^^^^
note: this value implements `FnOnce`, which causes it to be moved when called
--> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:9:5
|
LL | tick();
| ^^^^
error: aborting due to previous error

View File

@ -4,11 +4,16 @@ error[E0382]: borrow of moved value: `x`
LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | !x;
| - value moved here
| -- `x` moved due to usage in operator
LL |
LL | x.clone();
| ^ value borrowed here after move
|
note: calling this operator moves the left-hand side
--> $SRC_DIR/libcore/ops/bit.rs:LL:COL
|
LL | fn not(self) -> Self::Output;
| ^^^^
help: consider further restricting this bound
|
LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {

View File

@ -37,10 +37,16 @@ error[E0382]: borrow of moved value: `y`
LL | let y = *x;
| - move occurs because `y` has type `str`, which does not implement the `Copy` trait
LL | y.foo();
| - value moved here
| ----- `y` moved due to this method call
...
LL | println!("{}", &y);
| ^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
--> $DIR/borrow-after-move.rs:4:12
|
LL | fn foo(self) -> String;
| ^^^^
error[E0382]: borrow of moved value: `x`
--> $DIR/borrow-after-move.rs:39:24

View File

@ -34,9 +34,15 @@ error[E0382]: use of moved value: `y`
LL | let y = *x;
| - move occurs because `y` has type `str`, which does not implement the `Copy` trait
LL | y.foo();
| - value moved here
| ----- `y` moved due to this method call
LL | y.foo();
| ^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
--> $DIR/double-move.rs:4:12
|
LL | fn foo(self) -> String;
| ^^^^
error[E0382]: use of moved value: `x`
--> $DIR/double-move.rs:45:9

View File

@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
LL | pub fn foo(self) -> isize {
| ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
LL | self.bar();
| ---- value moved here
| ----- `self` moved due to this method call
LL | return self.x;
| ^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
--> $DIR/use-after-move-self-based-on-type.rs:15:16
|
LL | pub fn bar(self) {}
| ^^^^
error: aborting due to previous error

View File

@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
LL | pub fn foo(self) -> isize {
| ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
LL | self.bar();
| ---- value moved here
| ----- `self` moved due to this method call
LL | return *self.x;
| ^^^^^^^ value used here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
--> $DIR/use-after-move-self.rs:13:16
|
LL | pub fn bar(self) {}
| ^^^^
error: aborting due to previous error

View File

@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `start`
LL | let start = Mine{test:"Foo".to_string(), other_val:0};
| ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
LL | let end = Mine{other_val:1, ..start.make_string_bar()};
| ----- value moved here
| ----------------- `start` moved due to this method call
LL | println!("{}", start.test);
| ^^^^^^^^^^ value borrowed here after move
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `start`
--> $DIR/walk-struct-literal-with.rs:7:28
|
LL | fn make_string_bar(mut self) -> Mine{
| ^^^^
error: aborting due to previous error