Rollup merge of #72389 - Aaron1011:feature/move-fn-self-msg, r=nikomatsakis
Explain move errors that occur due to method calls involving `self` When calling a method that takes `self` (e.g. `vec.into_iter()`), the method receiver is moved out of. If the method receiver is used again, a move error will be emitted:: ```rust fn main() { let a = vec![true]; a.into_iter(); a; } ``` emits ``` error[E0382]: use of moved value: `a` --> src/main.rs:4:5 | 2 | let a = vec![true]; | - move occurs because `a` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait 3 | a.into_iter(); | - value moved here 4 | a; | ^ value used here after move ``` However, the error message doesn't make it clear that the move is caused by the call to `into_iter`. This PR adds additional messages to move errors when the move is caused by using a value as the receiver of a `self` method:: ``` error[E0382]: use of moved value: `a` --> vec.rs:4:5 | 2 | let a = vec![true]; | - move occurs because `a` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait 3 | a.into_iter(); | ------------- value moved due to this method call 4 | a; | ^ value used here after move | note: this function takes `self`, which moves the receiver --> /home/aaron/repos/rust/src/libcore/iter/traits/collect.rs:239:5 | 239 | fn into_iter(self) -> Self::IntoIter; ``` TODO: - [x] Add special handling for `FnOnce/FnMut/Fn` - we probably don't want to point at the unstable trait methods - [x] Consider adding additional context for operations (e.g. `Shr::shr`) when the call was generated using the operator syntax (e.g. `a >> b`) - [x] Consider pointing to the method parent (impl or trait block) in addition to the method itself.
This commit is contained in:
commit
372cb9b69c
@ -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;
|
||||
@ -25,6 +25,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
||||
let mut span = e.span;
|
||||
ensure_sufficient_stack(|| {
|
||||
let kind = match e.kind {
|
||||
ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
|
||||
@ -53,6 +54,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
|
||||
}
|
||||
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
||||
span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None);
|
||||
let binop = self.lower_binop(binop);
|
||||
let lhs = self.lower_expr(lhs);
|
||||
let rhs = self.lower_expr(rhs);
|
||||
@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
hir::Expr {
|
||||
hir_id: self.lower_node_id(e.id),
|
||||
kind,
|
||||
span: e.span,
|
||||
span,
|
||||
attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
|
||||
}
|
||||
})
|
||||
@ -237,6 +239,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
|
||||
let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None);
|
||||
Spanned {
|
||||
node: match b.node {
|
||||
BinOpKind::Add => hir::BinOpKind::Add,
|
||||
@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
BinOpKind::Ge => hir::BinOpKind::Ge,
|
||||
BinOpKind::Gt => hir::BinOpKind::Gt,
|
||||
},
|
||||
span: b.span,
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1360,9 +1363,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);
|
||||
@ -1457,10 +1465,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(
|
||||
|
@ -455,7 +455,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),
|
||||
|
@ -1317,13 +1317,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Symbol] {
|
||||
fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] {
|
||||
let param_names = match self.kind(id) {
|
||||
EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
|
||||
EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
|
||||
_ => Lazy::empty(),
|
||||
};
|
||||
tcx.arena.alloc_from_iter(param_names.decode(self))
|
||||
tcx.arena.alloc_from_iter(param_names.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn exported_symbols(
|
||||
|
@ -30,7 +30,7 @@ use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
|
||||
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
|
||||
use rustc_target::abi::VariantIdx;
|
||||
use std::hash::Hash;
|
||||
@ -997,18 +997,12 @@ impl EncodeContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Symbol]> {
|
||||
self.tcx.dep_graph.with_ignore(|| {
|
||||
let body = self.tcx.hir().body(body_id);
|
||||
self.lazy(body.params.iter().map(|arg| match arg.pat.kind {
|
||||
hir::PatKind::Binding(_, _, ident, _) => ident.name,
|
||||
_ => kw::Invalid,
|
||||
}))
|
||||
})
|
||||
fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
|
||||
self.tcx.dep_graph.with_ignore(|| self.lazy(self.tcx.hir().body_param_names(body_id)))
|
||||
}
|
||||
|
||||
fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> {
|
||||
self.lazy(param_names.iter().map(|ident| ident.name))
|
||||
fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Ident]> {
|
||||
self.lazy(param_names.iter())
|
||||
}
|
||||
|
||||
fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
|
||||
|
@ -19,7 +19,7 @@ use rustc_serialize::opaque::Encoder;
|
||||
use rustc_session::config::SymbolManglingVersion;
|
||||
use rustc_session::CrateDisambiguator;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{self, Span};
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
|
||||
@ -327,7 +327,7 @@ struct ModData {
|
||||
struct FnData {
|
||||
asyncness: hir::IsAsync,
|
||||
constness: hir::Constness,
|
||||
param_names: Lazy<[Symbol]>,
|
||||
param_names: Lazy<[Ident]>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
|
@ -14,7 +14,7 @@ use rustc_hir::*;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
@ -375,6 +375,13 @@ impl<'hir> Map<'hir> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn body_param_names(&self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir {
|
||||
self.body(id).params.iter().map(|arg| match arg.pat.kind {
|
||||
PatKind::Binding(_, _, ident, _) => ident,
|
||||
_ => Ident::new(kw::Invalid, rustc_span::DUMMY_SP),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
|
||||
///
|
||||
/// Panics if `LocalDefId` does not have an associated body.
|
||||
|
@ -12,10 +12,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
|
||||
use rustc_hir::Body;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::ItemLocalId;
|
||||
use rustc_hir::Node;
|
||||
use rustc_hir::*;
|
||||
use rustc_index::vec::IndexVec;
|
||||
|
||||
pub struct Owner<'tcx> {
|
||||
@ -79,5 +76,20 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||
};
|
||||
providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
|
||||
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
|
||||
providers.fn_arg_names = |tcx, id| {
|
||||
let hir = tcx.hir();
|
||||
let hir_id = hir.as_local_hir_id(id.expect_local());
|
||||
if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
|
||||
tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
|
||||
} else if let Node::TraitItem(&TraitItem {
|
||||
kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
|
||||
..
|
||||
}) = hir.get(hir_id)
|
||||
{
|
||||
tcx.arena.alloc_slice(idents)
|
||||
} else {
|
||||
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
|
||||
}
|
||||
};
|
||||
map::provide(providers);
|
||||
}
|
||||
|
@ -339,7 +339,9 @@ 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(_))
|
||||
| ExpnKind::Desugaring(DesugaringKind::Operator) => 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.
|
||||
|
@ -706,7 +706,7 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
Other {
|
||||
query fn_arg_names(def_id: DefId) -> &'tcx [Symbol] {
|
||||
query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] {
|
||||
desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
|
||||
}
|
||||
/// Gets the rendered value of the specified constant or associated constant.
|
||||
|
@ -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,13 +151,70 @@ 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 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,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// Used in a closure.
|
||||
(LaterUseKind::ClosureCapture, var_span)
|
||||
}
|
||||
UseSpans::OtherUse(span) => {
|
||||
UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => {
|
||||
let block = &self.body.basic_blocks()[location.block];
|
||||
|
||||
let kind = if let Some(&Statement {
|
||||
|
@ -11,7 +11,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 +37,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,33 +534,58 @@ 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 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::OtherUse(span) => span,
|
||||
UseSpans::ClosureUse { args_span: span, .. }
|
||||
| UseSpans::FnSelfUse { var_span: span, .. }
|
||||
| UseSpans::OtherUse(span) => span,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn var_or_use(self) -> Span {
|
||||
match self {
|
||||
UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span,
|
||||
UseSpans::ClosureUse { var_span: span, .. }
|
||||
| UseSpans::FnSelfUse { var_span: span, .. }
|
||||
| UseSpans::OtherUse(span) => span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,6 +654,7 @@ impl UseSpans {
|
||||
{
|
||||
match self {
|
||||
closure @ UseSpans::ClosureUse { .. } => closure,
|
||||
fn_self @ UseSpans::FnSelfUse { .. } => fn_self,
|
||||
UseSpans::OtherUse(_) => if_other(),
|
||||
}
|
||||
}
|
||||
@ -727,21 +758,100 @@ 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 };
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
OtherUse(stmt.source_info.span)
|
||||
let normal_ret = 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, .. }, .. }) =
|
||||
&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 is_fn_once = tcx.parent(method_did) == tcx.lang_items().fn_once_trait();
|
||||
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 fn_call_span.is_desugaring(DesugaringKind::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!(
|
||||
|
@ -277,6 +277,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(),
|
||||
@ -310,6 +311,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(),
|
||||
@ -486,6 +488,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.
|
||||
|
@ -511,6 +511,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,
|
||||
|
@ -822,7 +822,15 @@ pub enum DesugaringKind {
|
||||
OpaqueTy,
|
||||
Async,
|
||||
Await,
|
||||
ForLoop,
|
||||
ForLoop(ForLoopLoc),
|
||||
Operator,
|
||||
}
|
||||
|
||||
/// 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 +843,8 @@ impl DesugaringKind {
|
||||
DesugaringKind::QuestionMark => "operator `?`",
|
||||
DesugaringKind::TryBlock => "`try` block",
|
||||
DesugaringKind::OpaqueTy => "`impl Trait`",
|
||||
DesugaringKind::ForLoop => "`for` loop",
|
||||
DesugaringKind::ForLoop(_) => "`for` loop",
|
||||
DesugaringKind::Operator => "operator",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ pub mod edition;
|
||||
use edition::Edition;
|
||||
pub mod hygiene;
|
||||
use hygiene::Transparency;
|
||||
pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext};
|
||||
pub use hygiene::{
|
||||
DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind, SyntaxContext,
|
||||
};
|
||||
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
|
||||
|
||||
|
@ -6,14 +6,15 @@
|
||||
|
||||
static CMP: () = {
|
||||
let x = &0 as *const _;
|
||||
let _v = x == x;
|
||||
let _v = x == x; //~ NOTE in this
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
//~| NOTE pointer arithmetic or comparison
|
||||
//~| NOTE in this
|
||||
};
|
||||
|
||||
static INT_PTR_ARITH: () = unsafe {
|
||||
let x: usize = std::mem::transmute(&0);
|
||||
let _v = x + 0;
|
||||
let _v = x + 0; //~ NOTE in this
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
//~| NOTE pointer-to-integer cast
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ LL | let _v = x == x;
|
||||
| ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ptr_arith.rs:16:14
|
||||
--> $DIR/ptr_arith.rs:17:14
|
||||
|
|
||||
LL | let _v = x + 0;
|
||||
| ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
@ -18,7 +18,7 @@ help: skipping check for `const_compare_raw_pointers` feature
|
||||
LL | let _v = x == x;
|
||||
| ^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/ptr_arith.rs:15:20
|
||||
--> $DIR/ptr_arith.rs:16:20
|
||||
|
|
||||
LL | let x: usize = std::mem::transmute(&0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -18,8 +18,12 @@ fn y /* 0#0 */() { }
|
||||
Expansions:
|
||||
0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
|
||||
1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo")
|
||||
2: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator)
|
||||
3: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator)
|
||||
|
||||
SyntaxContexts:
|
||||
#0: parent: #0, outer_mark: (ExpnId(0), Opaque)
|
||||
#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
|
||||
#2: parent: #1, outer_mark: (ExpnId(2), Transparent)
|
||||
#3: parent: #1, outer_mark: (ExpnId(3), Transparent)
|
||||
*/
|
||||
|
@ -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 this method call
|
||||
LL |
|
||||
LL | x.clone();
|
||||
| ^ value borrowed here after move
|
||||
|
|
||||
note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
|
||||
--> $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