@@ -6,14 +6,14 @@ use crate::{
66use hir:: { def_id:: DefId , Body , HirId , HirIdMap } ;
77use rustc_data_structures:: stable_set:: FxHashSet ;
88use rustc_hir as hir;
9- use rustc_middle:: hir :: map :: Map ;
9+ use rustc_middle:: ty :: { ParamEnv , TyCtxt } ;
1010
1111pub ( super ) fn find_consumed_and_borrowed < ' a , ' tcx > (
1212 fcx : & ' a FnCtxt < ' a , ' tcx > ,
1313 def_id : DefId ,
1414 body : & ' tcx Body < ' tcx > ,
1515) -> 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 ) ;
1717 expr_use_visitor. consume_body ( fcx, def_id, body) ;
1818 expr_use_visitor. places
1919}
@@ -36,14 +36,16 @@ pub(super) struct ConsumedAndBorrowedPlaces {
3636/// Interesting values are those that are either dropped or borrowed. For dropped values, we also
3737/// record the parent expression, which is the point where the drop actually takes place.
3838struct ExprUseDelegate < ' tcx > {
39- hir : Map < ' tcx > ,
39+ tcx : TyCtxt < ' tcx > ,
40+ param_env : ParamEnv < ' tcx > ,
4041 places : ConsumedAndBorrowedPlaces ,
4142}
4243
4344impl < ' tcx > ExprUseDelegate < ' tcx > {
44- fn new ( hir : Map < ' tcx > ) -> Self {
45+ fn new ( tcx : TyCtxt < ' tcx > , param_env : ParamEnv < ' tcx > ) -> Self {
4546 Self {
46- hir,
47+ tcx,
48+ param_env,
4749 places : ConsumedAndBorrowedPlaces {
4850 consumed : <_ >:: default ( ) ,
4951 borrowed : <_ >:: default ( ) ,
@@ -77,7 +79,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
7779 place_with_id : & expr_use_visitor:: PlaceWithHirId < ' tcx > ,
7880 diag_expr_id : HirId ,
7981 ) {
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 ) {
8183 Some ( parent) => parent,
8284 None => place_with_id. hir_id ,
8385 } ;
@@ -108,20 +110,23 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
108110 diag_expr_id : HirId ,
109111 ) {
110112 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 ) {
119116 self . places
120117 . borrowed
121118 . insert ( TrackedValue :: from_place_with_projections_allowed ( assignee_place) ) ;
122119 }
123120 }
124121
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+
125130 fn fake_read (
126131 & mut self ,
127132 _place : expr_use_visitor:: Place < ' tcx > ,
0 commit comments