@@ -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