Auto merge of #106095 - estebank:pin-mut-reborrow, r=compiler-errors
Suggest `Pin::as_mut` when encountering borrow error Fix #65409 for `Pin<&mut T>`.
This commit is contained in:
commit
0ca50032ce
17 changed files with 205 additions and 23 deletions
|
@ -194,7 +194,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
|
|
||||||
if !seen_spans.contains(&move_span) {
|
if !seen_spans.contains(&move_span) {
|
||||||
if !closure {
|
if !closure {
|
||||||
self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
|
self.suggest_ref_or_clone(
|
||||||
|
mpi,
|
||||||
|
move_span,
|
||||||
|
&mut err,
|
||||||
|
&mut in_pattern,
|
||||||
|
move_spans,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.explain_captures(
|
self.explain_captures(
|
||||||
|
@ -312,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
move_span: Span,
|
move_span: Span,
|
||||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||||
in_pattern: &mut bool,
|
in_pattern: &mut bool,
|
||||||
|
move_spans: UseSpans<'_>,
|
||||||
) {
|
) {
|
||||||
struct ExpressionFinder<'hir> {
|
struct ExpressionFinder<'hir> {
|
||||||
expr_span: Span,
|
expr_span: Span,
|
||||||
|
@ -440,6 +447,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
) = call_expr.kind
|
) = call_expr.kind
|
||||||
{
|
{
|
||||||
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
|
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
|
||||||
|
} else if let UseSpans::FnSelfUse {
|
||||||
|
kind: CallKind::Normal { .. },
|
||||||
|
..
|
||||||
|
} = move_spans {
|
||||||
|
// We already suggest cloning for these cases in `explain_captures`.
|
||||||
} else {
|
} else {
|
||||||
self.suggest_cloning(err, ty, move_span);
|
self.suggest_cloning(err, ty, move_span);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, Namespace};
|
use rustc_hir::def::{CtorKind, Namespace};
|
||||||
use rustc_hir::GeneratorKind;
|
use rustc_hir::GeneratorKind;
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
|
||||||
use rustc_middle::mir::tcx::PlaceTy;
|
use rustc_middle::mir::tcx::PlaceTy;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
|
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
|
||||||
|
@ -18,7 +18,10 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
|
use rustc_trait_selection::traits::{
|
||||||
|
type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
|
||||||
|
};
|
||||||
|
|
||||||
use super::borrow_set::BorrowData;
|
use super::borrow_set::BorrowData;
|
||||||
use super::MirBorrowckCtxt;
|
use super::MirBorrowckCtxt;
|
||||||
|
@ -1066,18 +1069,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
CallKind::Normal { self_arg, desugaring, method_did } => {
|
CallKind::Normal { self_arg, desugaring, method_did } => {
|
||||||
let self_arg = self_arg.unwrap();
|
let self_arg = self_arg.unwrap();
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
|
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
|
||||||
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
|
let ty = moved_place.ty(self.body, tcx).ty;
|
||||||
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
|
let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
|
||||||
Some(def_id) => {
|
Some(def_id) => {
|
||||||
let infcx = self.infcx.tcx.infer_ctxt().build();
|
let infcx = self.infcx.tcx.infer_ctxt().build();
|
||||||
type_known_to_meet_bound_modulo_regions(
|
type_known_to_meet_bound_modulo_regions(
|
||||||
&infcx,
|
&infcx,
|
||||||
self.param_env,
|
self.param_env,
|
||||||
infcx.tcx.mk_imm_ref(
|
tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)),
|
||||||
infcx.tcx.lifetimes.re_erased,
|
|
||||||
infcx.tcx.erase_regions(ty),
|
|
||||||
),
|
|
||||||
def_id,
|
def_id,
|
||||||
DUMMY_SP,
|
DUMMY_SP,
|
||||||
)
|
)
|
||||||
|
@ -1133,8 +1134,44 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
place_name, partially_str, loop_message
|
place_name, partially_str, loop_message
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
let infcx = tcx.infer_ctxt().build();
|
||||||
|
let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty);
|
||||||
|
if let ty::Adt(def, substs) = ty.kind()
|
||||||
|
&& Some(def.did()) == tcx.lang_items().pin_type()
|
||||||
|
&& let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
|
||||||
|
&& let self_ty = infcx.replace_bound_vars_with_fresh_vars(
|
||||||
|
fn_call_span,
|
||||||
|
LateBoundRegionConversionTime::FnCall,
|
||||||
|
tcx.fn_sig(method_did).input(0),
|
||||||
|
)
|
||||||
|
&& infcx.can_eq(self.param_env, ty, self_ty).is_ok()
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
fn_call_span.shrink_to_lo(),
|
||||||
|
"consider reborrowing the `Pin` instead of moving it",
|
||||||
|
"as_mut().".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(clone_trait) = tcx.lang_items().clone_trait()
|
||||||
|
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
|
||||||
|
&& let o = Obligation::new(
|
||||||
|
tcx,
|
||||||
|
ObligationCause::dummy(),
|
||||||
|
self.param_env,
|
||||||
|
ty::Binder::dummy(trait_ref),
|
||||||
|
)
|
||||||
|
&& infcx.predicate_must_hold_modulo_regions(&o)
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
fn_call_span.shrink_to_lo(),
|
||||||
|
"you can `clone` the value and consume it, but this might not be \
|
||||||
|
your desired behavior",
|
||||||
|
"clone().".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let tcx = self.infcx.tcx;
|
|
||||||
// Avoid pointing to the same function in multiple different
|
// Avoid pointing to the same function in multiple different
|
||||||
// error messages.
|
// error messages.
|
||||||
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
|
||||||
|
|
|
@ -9,6 +9,10 @@ LL | let _x = Rc::new(vec![1, 2]).into_iter();
|
||||||
|
|
|
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves value
|
note: `into_iter` takes ownership of the receiver `self`, which moves value
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | let _x = Rc::new(vec![1, 2]).clone().into_iter();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// run-rustfix
|
||||||
|
// Test that a by-ref `FnMut` closure gets an error when it tries to
|
||||||
|
// consume a value.
|
||||||
|
|
||||||
|
fn call<F>(f: F) where F : Fn() {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let y = vec![format!("World")];
|
||||||
|
call(|| {
|
||||||
|
y.clone().into_iter();
|
||||||
|
//~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
// run-rustfix
|
||||||
// Test that a by-ref `FnMut` closure gets an error when it tries to
|
// Test that a by-ref `FnMut` closure gets an error when it tries to
|
||||||
// consume a value.
|
// consume a value.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
|
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
|
||||||
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
|
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9
|
||||||
|
|
|
|
||||||
LL | let y = vec![format!("World")];
|
LL | let y = vec![format!("World")];
|
||||||
| - captured outer variable
|
| - captured outer variable
|
||||||
|
@ -12,6 +12,10 @@ LL | y.into_iter();
|
||||||
|
|
|
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `y`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `y`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | y.clone().into_iter();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,10 @@ LL | println!("{:?}", some_vec);
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | some_vec.clone().into_iter();
|
LL | some_vec.clone().into_iter();
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ LL | val.0;
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
= note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
|
= note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | val.0.clone().into_iter().next();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error[E0382]: use of moved value: `foo`
|
error[E0382]: use of moved value: `foo`
|
||||||
--> $DIR/move-fn-self-receiver.rs:34:5
|
--> $DIR/move-fn-self-receiver.rs:34:5
|
||||||
|
@ -93,10 +97,10 @@ note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc
|
||||||
|
|
|
|
||||||
LL | fn use_rc_self(self: Rc<Self>) {}
|
LL | fn use_rc_self(self: Rc<Self>) {}
|
||||||
| ^^^^
|
| ^^^^
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | rc_foo.clone().use_rc_self();
|
LL | rc_foo.clone().use_rc_self();
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error[E0382]: use of moved value: `foo_add`
|
error[E0382]: use of moved value: `foo_add`
|
||||||
--> $DIR/move-fn-self-receiver.rs:59:5
|
--> $DIR/move-fn-self-receiver.rs:59:5
|
||||||
|
@ -136,10 +140,10 @@ LL | for _val in explicit_into_iter.into_iter() {}
|
||||||
LL | explicit_into_iter;
|
LL | explicit_into_iter;
|
||||||
| ^^^^^^^^^^^^^^^^^^ value used here after move
|
| ^^^^^^^^^^^^^^^^^^ value used here after move
|
||||||
|
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | for _val in explicit_into_iter.clone().into_iter() {}
|
LL | for _val in explicit_into_iter.clone().into_iter() {}
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error[E0382]: use of moved value: `container`
|
error[E0382]: use of moved value: `container`
|
||||||
--> $DIR/move-fn-self-receiver.rs:71:5
|
--> $DIR/move-fn-self-receiver.rs:71:5
|
||||||
|
|
|
@ -10,10 +10,10 @@ LL | touch(&x[0]);
|
||||||
|
|
|
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | consume(x.clone().into_iter().next().unwrap());
|
LL | consume(x.clone().into_iter().next().unwrap());
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -162,10 +162,10 @@ LL | touch(&x);
|
||||||
|
|
|
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | let _y = x.clone().into_iter().next().unwrap();
|
LL | let _y = x.clone().into_iter().next().unwrap();
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
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
|
||||||
|
@ -179,10 +179,10 @@ LL | touch(&x);
|
||||||
|
|
|
|
||||||
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
note: `into_iter` takes ownership of the receiver `self`, which moves `x`
|
||||||
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
|
||||||
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
|
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
|
||||||
| ++++++++
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to 11 previous errors
|
error: aborting due to 11 previous errors
|
||||||
|
|
||||||
|
|
15
src/test/ui/moves/pin-mut-reborrow.fixed
Normal file
15
src/test/ui/moves/pin-mut-reborrow.fixed
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// run-rustfix
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self: Pin<&mut Self>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut foo = Foo;
|
||||||
|
let mut foo = Pin::new(&mut foo);
|
||||||
|
foo.as_mut().foo();
|
||||||
|
foo.foo(); //~ ERROR use of moved value
|
||||||
|
}
|
15
src/test/ui/moves/pin-mut-reborrow.rs
Normal file
15
src/test/ui/moves/pin-mut-reborrow.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// run-rustfix
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
struct Foo;
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self: Pin<&mut Self>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut foo = Foo;
|
||||||
|
let mut foo = Pin::new(&mut foo);
|
||||||
|
foo.foo();
|
||||||
|
foo.foo(); //~ ERROR use of moved value
|
||||||
|
}
|
23
src/test/ui/moves/pin-mut-reborrow.stderr
Normal file
23
src/test/ui/moves/pin-mut-reborrow.stderr
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
error[E0382]: use of moved value: `foo`
|
||||||
|
--> $DIR/pin-mut-reborrow.rs:14:5
|
||||||
|
|
|
||||||
|
LL | let mut foo = Pin::new(&mut foo);
|
||||||
|
| ------- move occurs because `foo` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
|
||||||
|
LL | foo.foo();
|
||||||
|
| ----- `foo` moved due to this method call
|
||||||
|
LL | foo.foo();
|
||||||
|
| ^^^ value used here after move
|
||||||
|
|
|
||||||
|
note: `Foo::foo` takes ownership of the receiver `self`, which moves `foo`
|
||||||
|
--> $DIR/pin-mut-reborrow.rs:7:12
|
||||||
|
|
|
||||||
|
LL | fn foo(self: Pin<&mut Self>) {}
|
||||||
|
| ^^^^
|
||||||
|
help: consider reborrowing the `Pin` instead of moving it
|
||||||
|
|
|
||||||
|
LL | foo.as_mut().foo();
|
||||||
|
| +++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0382`.
|
11
src/test/ui/moves/suggest-clone.fixed
Normal file
11
src/test/ui/moves/suggest-clone.fixed
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Foo;
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self) {}
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
let foo = &Foo;
|
||||||
|
foo.clone().foo(); //~ ERROR cannot move out
|
||||||
|
}
|
11
src/test/ui/moves/suggest-clone.rs
Normal file
11
src/test/ui/moves/suggest-clone.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Foo;
|
||||||
|
impl Foo {
|
||||||
|
fn foo(self) {}
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
let foo = &Foo;
|
||||||
|
foo.foo(); //~ ERROR cannot move out
|
||||||
|
}
|
22
src/test/ui/moves/suggest-clone.stderr
Normal file
22
src/test/ui/moves/suggest-clone.stderr
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
error[E0507]: cannot move out of `*foo` which is behind a shared reference
|
||||||
|
--> $DIR/suggest-clone.rs:10:5
|
||||||
|
|
|
||||||
|
LL | foo.foo();
|
||||||
|
| ^^^^-----
|
||||||
|
| | |
|
||||||
|
| | `*foo` moved due to this method call
|
||||||
|
| move occurs because `*foo` has type `Foo`, which does not implement the `Copy` trait
|
||||||
|
|
|
||||||
|
note: `Foo::foo` takes ownership of the receiver `self`, which moves `*foo`
|
||||||
|
--> $DIR/suggest-clone.rs:6:12
|
||||||
|
|
|
||||||
|
LL | fn foo(self) {}
|
||||||
|
| ^^^^
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | foo.clone().foo();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0507`.
|
|
@ -9,6 +9,10 @@ LL | if selection.1.unwrap().contains(selection.0) {
|
||||||
|
|
|
|
||||||
note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
|
note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
|
||||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | if selection.1.clone().unwrap().contains(selection.0) {
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
|
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
|
||||||
--> $DIR/option-content-move.rs:27:20
|
--> $DIR/option-content-move.rs:27:20
|
||||||
|
@ -21,6 +25,10 @@ LL | if selection.1.unwrap().contains(selection.0) {
|
||||||
|
|
|
|
||||||
note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
|
note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
|
||||||
--> $SRC_DIR/core/src/result.rs:LL:COL
|
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||||
|
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||||
|
|
|
||||||
|
LL | if selection.1.clone().unwrap().contains(selection.0) {
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue