@@ -6,14 +6,14 @@ use crate::{
6
6
use hir::{def_id::DefId, Body, HirId, HirIdMap};
7
7
use rustc_data_structures::stable_set::FxHashSet;
8
8
use rustc_hir as hir;
9
- use rustc_middle::hir::map::Map ;
9
+ use rustc_middle::ty::{ParamEnv, TyCtxt} ;
10
10
11
11
pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
12
12
fcx: &'a FnCtxt<'a, 'tcx>,
13
13
def_id: DefId,
14
14
body: &'tcx Body<'tcx>,
15
15
) -> ConsumedAndBorrowedPlaces {
16
- let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx.hir() );
16
+ let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx, fcx.param_env );
17
17
expr_use_visitor.consume_body(fcx, def_id, body);
18
18
expr_use_visitor.places
19
19
}
@@ -36,14 +36,16 @@ pub(super) struct ConsumedAndBorrowedPlaces {
36
36
/// Interesting values are those that are either dropped or borrowed. For dropped values, we also
37
37
/// record the parent expression, which is the point where the drop actually takes place.
38
38
struct ExprUseDelegate<'tcx> {
39
- hir: Map<'tcx>,
39
+ tcx: TyCtxt<'tcx>,
40
+ param_env: ParamEnv<'tcx>,
40
41
places: ConsumedAndBorrowedPlaces,
41
42
}
42
43
43
44
impl<'tcx> ExprUseDelegate<'tcx> {
44
- fn new(hir: Map <'tcx>) -> Self {
45
+ fn new(tcx: TyCtxt<'tcx>, param_env: ParamEnv <'tcx>) -> Self {
45
46
Self {
46
- hir,
47
+ tcx,
48
+ param_env,
47
49
places: ConsumedAndBorrowedPlaces {
48
50
consumed: <_>::default(),
49
51
borrowed: <_>::default(),
@@ -77,7 +79,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
77
79
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
78
80
diag_expr_id: HirId,
79
81
) {
80
- let parent = match self.hir.find_parent_node(place_with_id.hir_id) {
82
+ let parent = match self.tcx. hir() .find_parent_node(place_with_id.hir_id) {
81
83
Some(parent) => parent,
82
84
None => place_with_id.hir_id,
83
85
};
@@ -108,20 +110,23 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
108
110
diag_expr_id: HirId,
109
111
) {
110
112
debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}");
111
- // Count mutations as a borrow when done through a projection.
112
- //
113
- // The goal here is to catch cases such as `x.y = 42`, since MIR will count this
114
- // as a borrow of `x`, and we need to match that behavior.
115
- //
116
- // FIXME(eholk): this is probably still more conservative than we need to be. For example,
117
- // we may need to count `*x = 42` as a borrow of `x`, since it overwrites all of `x`.
118
- if !assignee_place.place.projections.is_empty() {
113
+ // If the type being assigned needs dropped, then the mutation counts as a borrow
114
+ // since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
115
+ if assignee_place.place.base_ty.needs_drop(self.tcx, self.param_env) {
119
116
self.places
120
117
.borrowed
121
118
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
122
119
}
123
120
}
124
121
122
+ fn bind(
123
+ &mut self,
124
+ binding_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
125
+ diag_expr_id: HirId,
126
+ ) {
127
+ debug!("bind {binding_place:?}; diag_expr_id={diag_expr_id:?}");
128
+ }
129
+
125
130
fn fake_read(
126
131
&mut self,
127
132
_place: expr_use_visitor::Place<'tcx>,
0 commit comments