Skip to content

Commit 2d6a2ff

Browse files
committed
Create new inference context
1 parent ea7de0d commit 2d6a2ff

10 files changed

+94
-30
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

+33-29
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diagnostic};
66
use rustc_hir as hir;
77
use rustc_hir::def::{CtorKind, Namespace};
88
use rustc_hir::GeneratorKind;
9-
use rustc_infer::infer::TyCtxtInferExt;
9+
use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt};
1010
use rustc_middle::mir::tcx::PlaceTy;
1111
use rustc_middle::mir::{
1212
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
@@ -18,7 +18,10 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
1818
use rustc_span::def_id::LocalDefId;
1919
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
2020
use rustc_target::abi::VariantIdx;
21-
use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
21+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
22+
use rustc_trait_selection::traits::{
23+
type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
24+
};
2225

2326
use super::borrow_set::BorrowData;
2427
use super::MirBorrowckCtxt;
@@ -1131,13 +1134,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11311134
place_name, partially_str, loop_message
11321135
),
11331136
);
1134-
let ty = tcx.erase_regions(moved_place.ty(self.body, self.infcx.tcx).ty);
1137+
let infcx = tcx.infer_ctxt().build();
1138+
let ty = infcx.freshen(moved_place.ty(self.body, tcx).ty);
11351139
if let ty::Adt(def, substs) = ty.kind()
1136-
&& Some(def.did()) == self.infcx.tcx.lang_items().pin_type()
1140+
&& Some(def.did()) == tcx.lang_items().pin_type()
11371141
&& let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind()
1138-
// FIXME: this is a hack because we can't call `can_eq`
1139-
&& ty.to_string() ==
1140-
tcx.fn_sig(method_did).input(0).skip_binder().to_string()
1142+
&& let self_ty = infcx.freshen(
1143+
infcx.replace_bound_vars_with_fresh_vars(
1144+
fn_call_span,
1145+
LateBoundRegionConversionTime::FnCall,
1146+
tcx.fn_sig(method_did).input(0),
1147+
)
1148+
)
1149+
&& infcx.can_eq(self.param_env, ty, self_ty).is_ok()
11411150
{
11421151
err.span_suggestion_verbose(
11431152
fn_call_span.shrink_to_lo(),
@@ -1146,28 +1155,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11461155
Applicability::MaybeIncorrect,
11471156
);
11481157
}
1149-
if let Some(clone_trait) = tcx.lang_items().clone_trait() {
1150-
// We can't use `predicate_may_hold` or `can_eq` without ICEs in
1151-
// borrowck because of the inference context, so we do a poor-man's
1152-
// version here.
1153-
for impl_def_id in tcx.all_impls(clone_trait) {
1154-
if let Some(def_id) = impl_def_id.as_local()
1155-
&& let hir_id = tcx.hir().local_def_id_to_hir_id(def_id)
1156-
&& let hir::Node::Item(hir::Item {
1157-
kind: hir::ItemKind::Impl(_),
1158-
..
1159-
}) = tcx.hir().get(hir_id)
1160-
&& tcx.type_of(impl_def_id) == ty
1161-
{
1162-
err.span_suggestion_verbose(
1163-
fn_call_span.shrink_to_lo(),
1164-
"you can `clone` the value and consume it, but this might \
1165-
not be your desired behavior",
1166-
"clone().".to_string(),
1167-
Applicability::MaybeIncorrect,
1168-
);
1169-
}
1170-
}
1158+
if let Some(clone_trait) = tcx.lang_items().clone_trait()
1159+
&& let trait_ref = tcx.mk_trait_ref(clone_trait, [ty])
1160+
&& let o = Obligation::new(
1161+
tcx,
1162+
ObligationCause::dummy(),
1163+
self.param_env,
1164+
ty::Binder::dummy(trait_ref),
1165+
)
1166+
&& infcx.predicate_must_hold_modulo_regions(&o)
1167+
{
1168+
err.span_suggestion_verbose(
1169+
fn_call_span.shrink_to_lo(),
1170+
"you can `clone` the value and consume it, but this might not be \
1171+
your desired behavior",
1172+
"clone().".to_string(),
1173+
Applicability::MaybeIncorrect,
1174+
);
11711175
}
11721176
}
11731177
// Avoid pointing to the same function in multiple different

src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ LL | let _x = Rc::new(vec![1, 2]).into_iter();
99
|
1010
note: `into_iter` takes ownership of the receiver `self`, which moves value
1111
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
12+
help: you can `clone` the value and consume it, but this might not be your desired behavior
13+
|
14+
LL | let _x = Rc::new(vec![1, 2]).clone().into_iter();
15+
| ++++++++
1216

1317
error: aborting due to previous error
1418

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
// Test that a by-ref `FnMut` closure gets an error when it tries to
3+
// consume a value.
4+
5+
fn call<F>(f: F) where F : Fn() {
6+
f();
7+
}
8+
9+
fn main() {
10+
let y = vec![format!("World")];
11+
call(|| {
12+
y.clone().into_iter();
13+
//~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure
14+
});
15+
}

src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// run-rustfix
12
// Test that a by-ref `FnMut` closure gets an error when it tries to
23
// consume a value.
34

src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
2-
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
2+
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9
33
|
44
LL | let y = vec![format!("World")];
55
| - captured outer variable
@@ -12,6 +12,10 @@ LL | y.into_iter();
1212
|
1313
note: `into_iter` takes ownership of the receiver `self`, which moves `y`
1414
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
15+
help: you can `clone` the value and consume it, but this might not be your desired behavior
16+
|
17+
LL | y.clone().into_iter();
18+
| ++++++++
1519

1620
error: aborting due to previous error
1721

src/test/ui/codemap_tests/tab_3.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ help: consider cloning the value if the performance cost is acceptable
1616
|
1717
LL | some_vec.clone().into_iter();
1818
| ++++++++
19+
help: you can `clone` the value and consume it, but this might not be your desired behavior
20+
|
21+
LL | some_vec.clone().into_iter();
22+
| ++++++++
1923

2024
error: aborting due to previous error
2125

src/test/ui/moves/move-fn-self-receiver.stderr

+12
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ LL | val.0;
99
note: `into_iter` takes ownership of the receiver `self`, which moves `val.0`
1010
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
1111
= note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait
12+
help: you can `clone` the value and consume it, but this might not be your desired behavior
13+
|
14+
LL | val.0.clone().into_iter().next();
15+
| ++++++++
1216

1317
error[E0382]: use of moved value: `foo`
1418
--> $DIR/move-fn-self-receiver.rs:34:5
@@ -97,6 +101,10 @@ help: consider cloning the value if the performance cost is acceptable
97101
|
98102
LL | rc_foo.clone().use_rc_self();
99103
| ++++++++
104+
help: you can `clone` the value and consume it, but this might not be your desired behavior
105+
|
106+
LL | rc_foo.clone().use_rc_self();
107+
| ++++++++
100108

101109
error[E0382]: use of moved value: `foo_add`
102110
--> $DIR/move-fn-self-receiver.rs:59:5
@@ -140,6 +148,10 @@ help: consider cloning the value if the performance cost is acceptable
140148
|
141149
LL | for _val in explicit_into_iter.clone().into_iter() {}
142150
| ++++++++
151+
help: you can `clone` the value and consume it, but this might not be your desired behavior
152+
|
153+
LL | for _val in explicit_into_iter.clone().into_iter() {}
154+
| ++++++++
143155

144156
error[E0382]: use of moved value: `container`
145157
--> $DIR/move-fn-self-receiver.rs:71:5

src/test/ui/moves/moves-based-on-type-access-to-field.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ help: consider cloning the value if the performance cost is acceptable
1414
|
1515
LL | consume(x.clone().into_iter().next().unwrap());
1616
| ++++++++
17+
help: you can `clone` the value and consume it, but this might not be your desired behavior
18+
|
19+
LL | consume(x.clone().into_iter().next().unwrap());
20+
| ++++++++
1721

1822
error: aborting due to previous error
1923

src/test/ui/moves/moves-based-on-type-exprs.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ help: consider cloning the value if the performance cost is acceptable
166166
|
167167
LL | let _y = x.clone().into_iter().next().unwrap();
168168
| ++++++++
169+
help: you can `clone` the value and consume it, but this might not be your desired behavior
170+
|
171+
LL | let _y = x.clone().into_iter().next().unwrap();
172+
| ++++++++
169173

170174
error[E0382]: borrow of moved value: `x`
171175
--> $DIR/moves-based-on-type-exprs.rs:83:11
@@ -183,6 +187,10 @@ help: consider cloning the value if the performance cost is acceptable
183187
|
184188
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
185189
| ++++++++
190+
help: you can `clone` the value and consume it, but this might not be your desired behavior
191+
|
192+
LL | let _y = [x.clone().into_iter().next().unwrap(); 1];
193+
| ++++++++
186194

187195
error: aborting due to 11 previous errors
188196

src/test/ui/suggestions/option-content-move.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ LL | if selection.1.unwrap().contains(selection.0) {
99
|
1010
note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
1111
--> $SRC_DIR/core/src/option.rs:LL:COL
12+
help: you can `clone` the value and consume it, but this might not be your desired behavior
13+
|
14+
LL | if selection.1.clone().unwrap().contains(selection.0) {
15+
| ++++++++
1216

1317
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
1418
--> $DIR/option-content-move.rs:27:20
@@ -21,6 +25,10 @@ LL | if selection.1.unwrap().contains(selection.0) {
2125
|
2226
note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1`
2327
--> $SRC_DIR/core/src/result.rs:LL:COL
28+
help: you can `clone` the value and consume it, but this might not be your desired behavior
29+
|
30+
LL | if selection.1.clone().unwrap().contains(selection.0) {
31+
| ++++++++
2432

2533
error: aborting due to 2 previous errors
2634

0 commit comments

Comments
 (0)