Create new inference context
This commit is contained in:
parent
ea7de0d485
commit
2d6a2ff76e
@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
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::{
|
||||
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::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||
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::MirBorrowckCtxt;
|
||||
@ -1131,13 +1134,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
place_name, partially_str, loop_message
|
||||
),
|
||||
);
|
||||
let ty = tcx.erase_regions(moved_place.ty(self.body, self.infcx.tcx).ty);
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ty = infcx.freshen(moved_place.ty(self.body, tcx).ty);
|
||||
if let ty::Adt(def, substs) = ty.kind()
|
||||
&& Some(def.did()) == self.infcx.tcx.lang_items().pin_type()
|
||||
&& Some(def.did()) == tcx.lang_items().pin_type()
|
||||
&& let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
|
||||
// FIXME: this is a hack because we can't call `can_eq`
|
||||
&& ty.to_string() ==
|
||||
tcx.fn_sig(method_did).input(0).skip_binder().to_string()
|
||||
&& let self_ty = infcx.freshen(
|
||||
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(),
|
||||
@ -1146,28 +1155,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
if let Some(clone_trait) = tcx.lang_items().clone_trait() {
|
||||
// We can't use `predicate_may_hold` or `can_eq` without ICEs in
|
||||
// borrowck because of the inference context, so we do a poor-man's
|
||||
// version here.
|
||||
for impl_def_id in tcx.all_impls(clone_trait) {
|
||||
if let Some(def_id) = impl_def_id.as_local()
|
||||
&& let hir_id = tcx.hir().local_def_id_to_hir_id(def_id)
|
||||
&& let hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_),
|
||||
..
|
||||
}) = tcx.hir().get(hir_id)
|
||||
&& tcx.type_of(impl_def_id) == ty
|
||||
{
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Avoid pointing to the same function in multiple different
|
||||
|
@ -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
|
||||
--> $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
|
||||
|
||||
|
@ -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
|
||||
// consume a value.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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")];
|
||||
| - captured outer variable
|
||||
@ -12,6 +12,10 @@ LL | y.into_iter();
|
||||
|
|
||||
note: `into_iter` takes ownership of the receiver `self`, which moves `y`
|
||||
--> $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
|
||||
|
||||
|
@ -16,6 +16,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | some_vec.clone().into_iter();
|
||||
| ++++++++
|
||||
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||
|
|
||||
LL | some_vec.clone().into_iter();
|
||||
| ++++++++
|
||||
|
||||
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`
|
||||
--> $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
|
||||
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`
|
||||
--> $DIR/move-fn-self-receiver.rs:34:5
|
||||
@ -97,6 +101,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | rc_foo.clone().use_rc_self();
|
||||
| ++++++++
|
||||
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
||||
|
|
||||
LL | rc_foo.clone().use_rc_self();
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `foo_add`
|
||||
--> $DIR/move-fn-self-receiver.rs:59:5
|
||||
@ -140,6 +148,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | for _val in explicit_into_iter.clone().into_iter() {}
|
||||
| ++++++++
|
||||
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() {}
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: use of moved value: `container`
|
||||
--> $DIR/move-fn-self-receiver.rs:71:5
|
||||
|
@ -14,6 +14,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | consume(x.clone().into_iter().next().unwrap());
|
||||
| ++++++++
|
||||
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());
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -166,6 +166,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _y = x.clone().into_iter().next().unwrap();
|
||||
| ++++++++
|
||||
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();
|
||||
| ++++++++
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/moves-based-on-type-exprs.rs:83:11
|
||||
@ -183,6 +187,10 @@ help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
|
||||
| ++++++++
|
||||
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];
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
@ -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`
|
||||
--> $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
|
||||
--> $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`
|
||||
--> $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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user