mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
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:
parent
36ac08e264
commit
fa6a61c689
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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`)
|
||||
|
@ -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`.
|
||||
|
@ -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!(
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
74
src/test/ui/moves/move-fn-self-receiver.rs
Normal file
74
src/test/ui/moves/move-fn-self-receiver.rs
Normal 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() {}
|
158
src/test/ui/moves/move-fn-self-receiver.stderr
Normal file
158
src/test/ui/moves/move-fn-self-receiver.stderr
Normal 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`.
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user