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:
Ralf Jung 2020-06-15 09:57:22 +02:00 committed by GitHub
commit 372cb9b69c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 729 additions and 103 deletions

View File

@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; 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_span::symbol::{sym, Ident, Symbol};
use rustc_target::asm; use rustc_target::asm;
use std::collections::hash_map::Entry; 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> { pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
let mut span = e.span;
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
let kind = match e.kind { let kind = match e.kind {
ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), 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) hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
} }
ExprKind::Binary(binop, ref lhs, ref rhs) => { 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 binop = self.lower_binop(binop);
let lhs = self.lower_expr(lhs); let lhs = self.lower_expr(lhs);
let rhs = self.lower_expr(rhs); let rhs = self.lower_expr(rhs);
@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::Expr { hir::Expr {
hir_id: self.lower_node_id(e.id), hir_id: self.lower_node_id(e.id),
kind, kind,
span: e.span, span,
attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(), 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 { fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None);
Spanned { Spanned {
node: match b.node { node: match b.node {
BinOpKind::Add => hir::BinOpKind::Add, BinOpKind::Add => hir::BinOpKind::Add,
@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
BinOpKind::Ge => hir::BinOpKind::Ge, BinOpKind::Ge => hir::BinOpKind::Ge,
BinOpKind::Gt => hir::BinOpKind::Gt, BinOpKind::Gt => hir::BinOpKind::Gt,
}, },
span: b.span, span,
} }
} }
@ -1360,9 +1363,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Block, body: &Block,
opt_label: Option<Label>, opt_label: Option<Label>,
) -> hir::Expr<'hir> { ) -> hir::Expr<'hir> {
let orig_head_span = head.span;
// expand <head> // expand <head>
let mut head = self.lower_expr_mut(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; head.span = desugared_span;
let iter = Ident::with_dummy_span(sym::iter); let iter = Ident::with_dummy_span(sym::iter);
@ -1457,10 +1465,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `mut iter => { ... }` // `mut iter => { ... }`
let iter_arm = self.arm(iter_pat, loop_expr); 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>) { ... }` // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = { let into_iter_expr = {
let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter]; 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( let match_expr = self.arena.alloc(self.expr_match(

View File

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

View File

@ -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) { let param_names = match self.kind(id) {
EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
_ => Lazy::empty(), _ => Lazy::empty(),
}; };
tcx.arena.alloc_from_iter(param_names.decode(self)) tcx.arena.alloc_from_iter(param_names.decode((self, tcx)))
} }
fn exported_symbols( fn exported_symbols(

View File

@ -30,7 +30,7 @@ use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
use rustc_span::source_map::Spanned; 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_span::{self, ExternalSource, FileName, SourceFile, Span};
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use std::hash::Hash; 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]> { fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
self.tcx.dep_graph.with_ignore(|| { self.tcx.dep_graph.with_ignore(|| self.lazy(self.tcx.hir().body_param_names(body_id)))
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(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> { fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Ident]> {
self.lazy(param_names.iter().map(|ident| ident.name)) self.lazy(param_names.iter())
} }
fn encode_optimized_mir(&mut self, def_id: LocalDefId) { fn encode_optimized_mir(&mut self, def_id: LocalDefId) {

View File

@ -19,7 +19,7 @@ use rustc_serialize::opaque::Encoder;
use rustc_session::config::SymbolManglingVersion; use rustc_session::config::SymbolManglingVersion;
use rustc_session::CrateDisambiguator; use rustc_session::CrateDisambiguator;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol; use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{self, Span}; use rustc_span::{self, Span};
use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc_target::spec::{PanicStrategy, TargetTriple};
@ -327,7 +327,7 @@ struct ModData {
struct FnData { struct FnData {
asyncness: hir::IsAsync, asyncness: hir::IsAsync,
constness: hir::Constness, constness: hir::Constness,
param_names: Lazy<[Symbol]>, param_names: Lazy<[Ident]>,
} }
#[derive(RustcEncodable, RustcDecodable)] #[derive(RustcEncodable, RustcDecodable)]

View File

@ -14,7 +14,7 @@ use rustc_hir::*;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::Spanned; 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_span::Span;
use rustc_target::spec::abi::Abi; 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`. /// Returns the `BodyOwnerKind` of this `LocalDefId`.
/// ///
/// Panics if `LocalDefId` does not have an associated body. /// Panics if `LocalDefId` does not have an associated body.

View File

@ -12,10 +12,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::Body; use rustc_hir::*;
use rustc_hir::HirId;
use rustc_hir::ItemLocalId;
use rustc_hir::Node;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
pub struct Owner<'tcx> { 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 = |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.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); map::provide(providers);
} }

View File

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

View File

@ -706,7 +706,7 @@ rustc_queries! {
} }
Other { 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) } 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. /// Gets the rendered value of the specified constant or associated constant.

View File

@ -24,7 +24,8 @@ use crate::borrow_check::{
}; };
use super::{ use super::{
explain_borrow::BorrowExplanation, IncludingDowncast, RegionName, RegionNameSource, UseSpans, explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
RegionNameSource, UseSpans,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -150,13 +151,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
format!("value moved{} here, in previous iteration of loop", move_msg), format!("value moved{} here, in previous iteration of loop", move_msg),
); );
} else { } else {
err.span_label(move_span, format!("value moved{} here", move_msg)); if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } =
move_spans.var_span_label( move_spans
&mut err, {
format!("variable moved due to use{}", move_spans.describe()), 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; let sess = self.infcx.tcx.sess;
if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) { if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
err.span_suggestion( err.span_suggestion(

View File

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

View File

@ -11,7 +11,11 @@ use rustc_middle::mir::{
}; };
use rustc_middle::ty::print::Print; use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt}; 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 rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData; use super::borrow_set::BorrowData;
@ -33,6 +37,7 @@ crate use mutability_errors::AccessKind;
crate use outlives_suggestion::OutlivesSuggestionBuilder; crate use outlives_suggestion::OutlivesSuggestionBuilder;
crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
crate use region_name::{RegionName, RegionNameSource}; crate use region_name::{RegionName, RegionNameSource};
use rustc_span::symbol::Ident;
pub(super) struct IncludingDowncast(pub(super) bool); 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)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(super) enum UseSpans { 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 { 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>, generator_kind: Option<GeneratorKind>,
// The span of the args of the closure, including the `move` keyword if /// The span of the args of the closure, including the `move` keyword if
// it's present. /// it's present.
args_span: Span, 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, 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. // This access has a single span associated to it: common case.
OtherUse(Span), 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 { impl UseSpans {
pub(super) fn args_or_use(self) -> Span { pub(super) fn args_or_use(self) -> Span {
match self { 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 { pub(super) fn var_or_use(self) -> Span {
match self { 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 { match self {
closure @ UseSpans::ClosureUse { .. } => closure, closure @ UseSpans::ClosureUse { .. } => closure,
fn_self @ UseSpans::FnSelfUse { .. } => fn_self,
UseSpans::OtherUse(_) => if_other(), 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); debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { 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::Closure(def_id, _)
| box AggregateKind::Generator(def_id, _, _) => def_id, | box AggregateKind::Generator(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)
debug!("move_spans: def_id={:?} places={:?}", def_id, places); {
if let Some((args_span, generator_kind, var_span)) = return ClosureUse { generator_kind, args_span, 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`) /// Finds the span of arguments of a closure (within `maybe_closure_span`)

View File

@ -408,7 +408,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
format!("{}.as_ref()", snippet), format!("{}.as_ref()", snippet),
Applicability::MaybeIncorrect, 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) && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id)
{ {
// FIXME: suggest for anything that implements `IntoIterator`. // FIXME: suggest for anything that implements `IntoIterator`.

View File

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

View File

@ -277,6 +277,7 @@ fn do_mir_borrowck<'a, 'tcx>(
move_data: &move_data, move_data: &move_data,
location_table: &LocationTable::new(promoted_body), location_table: &LocationTable::new(promoted_body),
movable_generator, movable_generator,
fn_self_span_reported: Default::default(),
locals_are_invalidated_at_exit, locals_are_invalidated_at_exit,
access_place_error_reported: Default::default(), access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(), reservation_error_reported: Default::default(),
@ -310,6 +311,7 @@ fn do_mir_borrowck<'a, 'tcx>(
location_table, location_table,
movable_generator, movable_generator,
locals_are_invalidated_at_exit, locals_are_invalidated_at_exit,
fn_self_span_reported: Default::default(),
access_place_error_reported: Default::default(), access_place_error_reported: Default::default(),
reservation_error_reported: Default::default(), reservation_error_reported: Default::default(),
reservation_warnings: 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` // but it is currently inconvenient to track down the `BorrowIndex`
// at the time we detect and report a reservation error. // at the time we detect and report a reservation error.
reservation_error_reported: FxHashSet<Place<'tcx>>, 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 /// Migration warnings to be reported for #56254. We delay reporting these
/// so that we can suppress the warning if there's a corresponding error /// so that we can suppress the warning if there's a corresponding error
/// for the activation of the borrow. /// for the activation of the borrow.

View File

@ -511,6 +511,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// This is basically `force_bits`. // This is basically `force_bits`.
let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok()); 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) { 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( self.report_assert_as_lint(
lint::builtin::ARITHMETIC_OVERFLOW, lint::builtin::ARITHMETIC_OVERFLOW,
source_info, source_info,

View File

@ -822,7 +822,15 @@ pub enum DesugaringKind {
OpaqueTy, OpaqueTy,
Async, Async,
Await, 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 { impl DesugaringKind {
@ -835,7 +843,8 @@ impl DesugaringKind {
DesugaringKind::QuestionMark => "operator `?`", DesugaringKind::QuestionMark => "operator `?`",
DesugaringKind::TryBlock => "`try` block", DesugaringKind::TryBlock => "`try` block",
DesugaringKind::OpaqueTy => "`impl Trait`", DesugaringKind::OpaqueTy => "`impl Trait`",
DesugaringKind::ForLoop => "`for` loop", DesugaringKind::ForLoop(_) => "`for` loop",
DesugaringKind::Operator => "operator",
} }
} }
} }

View File

@ -31,7 +31,9 @@ pub mod edition;
use edition::Edition; use edition::Edition;
pub mod hygiene; pub mod hygiene;
use hygiene::Transparency; 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; pub mod def_id;
use def_id::{CrateNum, DefId, LOCAL_CRATE}; use def_id::{CrateNum, DefId, LOCAL_CRATE};
mod span_encoding; mod span_encoding;

View File

@ -4,10 +4,15 @@ error[E0382]: use of moved value: `lhs`
LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs + rhs; LL | lhs + rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs - rhs; LL | lhs - rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs * rhs; LL | lhs * rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs / rhs; LL | lhs / rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs % rhs; LL | lhs % rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs & rhs; LL | lhs & rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs | rhs; LL | lhs | rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs ^ rhs; LL | lhs ^ rhs;
| --- value moved here | --------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs << rhs; LL | lhs << rhs;
| --- value moved here | ---------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) { 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) { 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 | --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
LL | lhs >> rhs; LL | lhs >> rhs;
| --- value moved here | ---------- `lhs` moved due to usage in operator
LL | drop(lhs); LL | drop(lhs);
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) { LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {

View File

@ -1,14 +1,21 @@
error[E0382]: use of moved value: `x` error[E0382]: use of moved value: `x`
--> $DIR/binop-move-semantics.rs:8:5 --> $DIR/binop-move-semantics.rs:8:5
| |
LL | fn double_move<T: Add<Output=()>>(x: T) { LL | fn double_move<T: Add<Output=()>>(x: T) {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait | - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | x LL | / x
| - value moved here LL | | +
LL | + LL | | x;
LL | x; | | ^
| ^ value used here after move | | |
| |_____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 help: consider further restricting this bound
| |
LL | fn double_move<T: Add<Output=()> + Copy>(x: T) { LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {

View File

@ -22,10 +22,15 @@ error[E0382]: use of moved value: `f`
LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) { LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
| - move occurs because `f` has type `F`, which does not implement the `Copy` trait | - move occurs because `f` has type `F`, which does not implement the `Copy` trait
LL | f(1, 2); LL | f(1, 2);
| - value moved here | ------- `f` moved due to this call
LL | f(1, 2); LL | f(1, 2);
| ^ value used here after move | ^ 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 help: consider further restricting this bound
| |
LL | fn c<F:FnOnce(isize, isize) -> isize + Copy>(f: F) { LL | fn c<F:FnOnce(isize, isize) -> isize + Copy>(f: F) {

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `debug_dump_dict`
--> $DIR/issue-42065.rs:11:5 --> $DIR/issue-42065.rs:11:5
| |
LL | debug_dump_dict(); LL | debug_dump_dict();
| --------------- value moved here | ----------------- `debug_dump_dict` moved due to this call
LL | debug_dump_dict(); LL | debug_dump_dict();
| ^^^^^^^^^^^^^^^ value used here after move | ^^^^^^^^^^^^^^^ 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 { 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 error: aborting due to previous error

View File

@ -4,10 +4,16 @@ error[E0382]: borrow of moved value: `some_vec`
LL | let some_vec = vec!["hi"]; LL | let some_vec = vec!["hi"];
| -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait | -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
LL | some_vec.into_iter(); LL | some_vec.into_iter();
| -------- value moved here | ----------- `some_vec` moved due to this method call
LL | { LL | {
LL | println!("{:?}", some_vec); LL | println!("{:?}", some_vec);
| ^^^^^^^^ value borrowed here after move | ^^^^^^^^ 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 error: aborting due to previous error

View File

@ -6,14 +6,15 @@
static CMP: () = { static CMP: () = {
let x = &0 as *const _; let x = &0 as *const _;
let _v = x == x; let _v = x == x; //~ NOTE in this
//~^ ERROR could not evaluate static initializer //~^ ERROR could not evaluate static initializer
//~| NOTE pointer arithmetic or comparison //~| NOTE pointer arithmetic or comparison
//~| NOTE in this
}; };
static INT_PTR_ARITH: () = unsafe { static INT_PTR_ARITH: () = unsafe {
let x: usize = std::mem::transmute(&0); let x: usize = std::mem::transmute(&0);
let _v = x + 0; let _v = x + 0; //~ NOTE in this
//~^ ERROR could not evaluate static initializer //~^ ERROR could not evaluate static initializer
//~| NOTE pointer-to-integer cast //~| NOTE pointer-to-integer cast
}; };

View File

@ -5,7 +5,7 @@ LL | let _v = x == x;
| ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants | ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
error[E0080]: could not evaluate static initializer error[E0080]: could not evaluate static initializer
--> $DIR/ptr_arith.rs:16:14 --> $DIR/ptr_arith.rs:17:14
| |
LL | let _v = x + 0; LL | let _v = x + 0;
| ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants | ^^^^^ "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; LL | let _v = x == x;
| ^^^^^^ | ^^^^^^
help: skipping check that does not even have a feature gate 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); LL | let x: usize = std::mem::transmute(&0);
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -18,8 +18,12 @@ fn y /* 0#0 */() { }
Expansions: Expansions:
0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root 0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo") 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: SyntaxContexts:
#0: parent: #0, outer_mark: (ExpnId(0), Opaque) #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
#1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent) #1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
#2: parent: #1, outer_mark: (ExpnId(2), Transparent)
#3: parent: #1, outer_mark: (ExpnId(3), Transparent)
*/ */

View File

@ -2,10 +2,15 @@ error[E0382]: use of moved value: `f`
--> $DIR/issue-12127.rs:11:9 --> $DIR/issue-12127.rs:11:9
| |
LL | f(); LL | f();
| - value moved here | --- `f` moved due to this call
LL | f(); LL | f();
| ^ value used here after move | ^ 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 = 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 error: aborting due to previous error

View File

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

View File

@ -17,6 +17,16 @@ LL | for _ in HashMap::new().iter().cloned() {}
found reference `&_` found reference `&_`
= note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>` = 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`. For more information about this error, try `rustc --explain E0271`.

View File

@ -5,14 +5,19 @@ LL | pub fn baz<T: Foo>(x: T) -> T {
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait | - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | if 0 == 1 { LL | if 0 == 1 {
LL | bar::bar(x.zero()) LL | bar::bar(x.zero())
| - value moved here | ------ `x` moved due to this method call
LL | } else { LL | } else {
LL | x.zero() LL | x.zero()
| - value moved here | ------ `x` moved due to this method call
LL | }; LL | };
LL | x.zero() LL | x.zero()
| ^ value used here after move | ^ 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 help: consider further restricting this bound
| |
LL | pub fn baz<T: Foo + Copy>(x: T) -> T { LL | pub fn baz<T: Foo + Copy>(x: T) -> T {

View File

@ -6,11 +6,17 @@ LL | let mut bad_letters = vec!['e', 't', 'o', 'i'];
LL | for l in bad_letters { 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` | help: consider borrowing to avoid moving into the for loop: `&bad_letters`
... ...
LL | bad_letters.push('s'); LL | bad_letters.push('s');
| ^^^^^^^^^^^ value borrowed here after move | ^^^^^^^^^^^ 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 error: aborting due to previous error

View File

@ -6,12 +6,18 @@ LL | let orig = vec![true];
LL | for _val in orig {} 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` | help: consider borrowing to avoid moving into the for loop: `&orig`
LL | let _closure = || orig; LL | let _closure = || orig;
| ^^ ---- use occurs due to use in closure | ^^ ---- use occurs due to use in closure
| | | |
| value used here after move | 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 error: aborting due to previous error

View File

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

View File

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

View File

@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `x`
LL | let x = vec!["hi".to_string()]; 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 | - 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()); LL | consume(x.into_iter().next().unwrap());
| - value moved here | ----------- `x` moved due to this method call
LL | touch(&x[0]); LL | touch(&x[0]);
| ^ value borrowed here after move | ^ 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 error: aborting due to previous error

View File

@ -104,9 +104,15 @@ error[E0382]: borrow of moved value: `x`
LL | let x = vec!["hi".to_string()]; 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 | - 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(); LL | let _y = x.into_iter().next().unwrap();
| - value moved here | ----------- `x` moved due to this method call
LL | touch(&x); LL | touch(&x);
| ^^ value borrowed here after move | ^^ 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` error[E0382]: borrow of moved value: `x`
--> $DIR/moves-based-on-type-exprs.rs:83:11 --> $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()]; 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 | - 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]; LL | let _y = [x.into_iter().next().unwrap(); 1];
| - value moved here | ----------- `x` moved due to this method call
LL | touch(&x); LL | touch(&x);
| ^^ value borrowed here after move | ^^ 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 error: aborting due to 11 previous errors

View File

@ -4,10 +4,15 @@ error[E0382]: use of moved value: `blk`
LL | fn foo<F:FnOnce()>(blk: F) { LL | fn foo<F:FnOnce()>(blk: F) {
| --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
LL | blk(); LL | blk();
| --- value moved here | ----- `blk` moved due to this call
LL | blk(); LL | blk();
| ^^^ value used here after move | ^^^ 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 help: consider further restricting this bound
| |
LL | fn foo<F:FnOnce() + Copy>(blk: F) { LL | fn foo<F:FnOnce() + Copy>(blk: F) {

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
--> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5 --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5
| |
LL | tick(); LL | tick();
| ---- value moved here | ------ `tick` moved due to this call
LL | tick(); LL | tick();
| ^^^^ value used here after move | ^^^^ 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); 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 error: aborting due to previous error

View File

@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
--> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5 --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5
| |
LL | tick(); LL | tick();
| ---- value moved here | ------ `tick` moved due to this call
LL | tick(); LL | tick();
| ^^^^ value used here after move | ^^^^ 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); 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 error: aborting due to previous error

View File

@ -4,11 +4,16 @@ error[E0382]: borrow of moved value: `x`
LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) { 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 | - move occurs because `x` has type `T`, which does not implement the `Copy` trait
LL | !x; LL | !x;
| - value moved here | -- `x` moved due to this method call
LL | LL |
LL | x.clone(); LL | x.clone();
| ^ value borrowed here after move | ^ 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 help: consider further restricting this bound
| |
LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) { LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {

View File

@ -37,10 +37,16 @@ error[E0382]: borrow of moved value: `y`
LL | let y = *x; LL | let y = *x;
| - move occurs because `y` has type `str`, which does not implement the `Copy` trait | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
LL | y.foo(); LL | y.foo();
| - value moved here | ----- `y` moved due to this method call
... ...
LL | println!("{}", &y); LL | println!("{}", &y);
| ^^ value borrowed here after move | ^^ 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` error[E0382]: borrow of moved value: `x`
--> $DIR/borrow-after-move.rs:39:24 --> $DIR/borrow-after-move.rs:39:24

View File

@ -34,9 +34,15 @@ error[E0382]: use of moved value: `y`
LL | let y = *x; LL | let y = *x;
| - move occurs because `y` has type `str`, which does not implement the `Copy` trait | - move occurs because `y` has type `str`, which does not implement the `Copy` trait
LL | y.foo(); LL | y.foo();
| - value moved here | ----- `y` moved due to this method call
LL | y.foo(); LL | y.foo();
| ^ value used here after move | ^ 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` error[E0382]: use of moved value: `x`
--> $DIR/double-move.rs:45:9 --> $DIR/double-move.rs:45:9

View File

@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
LL | pub fn foo(self) -> isize { LL | pub fn foo(self) -> isize {
| ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
LL | self.bar(); LL | self.bar();
| ---- value moved here | ----- `self` moved due to this method call
LL | return self.x; LL | return self.x;
| ^^^^^^ value used here after move | ^^^^^^ 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 error: aborting due to previous error

View File

@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
LL | pub fn foo(self) -> isize { LL | pub fn foo(self) -> isize {
| ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait | ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
LL | self.bar(); LL | self.bar();
| ---- value moved here | ----- `self` moved due to this method call
LL | return *self.x; LL | return *self.x;
| ^^^^^^^ value used here after move | ^^^^^^^ 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 error: aborting due to previous error

View File

@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `start`
LL | let start = Mine{test:"Foo".to_string(), other_val:0}; 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 | ----- 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()}; 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); LL | println!("{}", start.test);
| ^^^^^^^^^^ value borrowed here after move | ^^^^^^^^^^ 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 error: aborting due to previous error