@@ -11,7 +11,7 @@ use rustc_middle::mir::{
1111    PlaceRef ,  ProjectionElem ,  Rvalue ,  Statement ,  StatementKind ,  Terminator ,  TerminatorKind , 
1212} ; 
1313use  rustc_middle:: ty:: print:: Print ; 
14- use  rustc_middle:: ty:: { self ,  DefIdTree ,  Ty ,  TyCtxt } ; 
14+ use  rustc_middle:: ty:: { self ,  DefIdTree ,  Instance ,   Ty ,  TyCtxt } ; 
1515use  rustc_span:: { 
1616    hygiene:: { DesugaringKind ,  ForLoopLoc } , 
1717    symbol:: sym, 
@@ -538,7 +538,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
538538
539539/// The span(s) associated to a use of a place. 
540540#[ derive( Copy ,  Clone ,  PartialEq ,  Eq ,  Debug ) ]  
541- pub ( super )  enum  UseSpans  { 
541+ pub ( super )  enum  UseSpans < ' tcx >  { 
542542    /// The access is caused by capturing a variable for a closure. 
543543     ClosureUse  { 
544544        /// This is true if the captured variable was from a generator. 
@@ -558,7 +558,7 @@ pub(super) enum UseSpans {
558558         fn_call_span :  Span , 
559559        /// The definition span of the method being called 
560560         fn_span :  Span , 
561-         kind :  FnSelfUseKind , 
561+         kind :  FnSelfUseKind < ' tcx > , 
562562    } , 
563563    /// This access is caused by a `match` or `if let` pattern. 
564564     PatUse ( Span ) , 
@@ -567,31 +567,44 @@ pub(super) enum UseSpans {
567567} 
568568
569569#[ derive( Copy ,  Clone ,  PartialEq ,  Eq ,  Debug ) ]  
570- pub ( super )  enum  FnSelfUseKind  { 
570+ pub ( super )  enum  FnSelfUseKind < ' tcx >  { 
571571    /// A normal method call of the form `receiver.foo(a, b, c)` 
572572     Normal  {  self_arg :  Ident ,  implicit_into_iter :  bool  } , 
573573    /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)` 
574574     FnOnceCall , 
575575    /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`) 
576576     Operator  {  self_arg :  Ident  } , 
577+     DerefCoercion  { 
578+         /// The `Span` of the `Target` associated type 
579+          /// in the `Deref` impl we are using. 
580+          deref_target :  Span , 
581+         /// The type `T::Deref` we are dereferencing to 
582+          deref_target_ty :  Ty < ' tcx > , 
583+     } , 
577584} 
578585
579- impl  UseSpans  { 
586+ impl  UseSpans < ' _ >  { 
580587    pub ( super )  fn  args_or_use ( self )  -> Span  { 
581588        match  self  { 
582589            UseSpans :: ClosureUse  {  args_span :  span,  .. } 
583590            | UseSpans :: PatUse ( span) 
584-             | UseSpans :: FnSelfUse  {  var_span :  span,  .. } 
585591            | UseSpans :: OtherUse ( span)  => span, 
592+             UseSpans :: FnSelfUse  { 
593+                 fn_call_span,  kind :  FnSelfUseKind :: DerefCoercion  {  .. } ,  ..
594+             }  => fn_call_span, 
595+             UseSpans :: FnSelfUse  {  var_span,  .. }  => var_span, 
586596        } 
587597    } 
588598
589599    pub ( super )  fn  var_or_use ( self )  -> Span  { 
590600        match  self  { 
591601            UseSpans :: ClosureUse  {  var_span :  span,  .. } 
592602            | UseSpans :: PatUse ( span) 
593-             | UseSpans :: FnSelfUse  {  var_span :  span,  .. } 
594603            | UseSpans :: OtherUse ( span)  => span, 
604+             UseSpans :: FnSelfUse  { 
605+                 fn_call_span,  kind :  FnSelfUseKind :: DerefCoercion  {  .. } ,  ..
606+             }  => fn_call_span, 
607+             UseSpans :: FnSelfUse  {  var_span,  .. }  => var_span, 
595608        } 
596609    } 
597610
@@ -754,7 +767,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
754767        & self , 
755768        moved_place :  PlaceRef < ' tcx > ,  // Could also be an upvar. 
756769        location :  Location , 
757-     )  -> UseSpans  { 
770+     )  -> UseSpans < ' tcx >  { 
758771        use  self :: UseSpans :: * ; 
759772
760773        let  stmt = match  self . body [ location. block ] . statements . get ( location. statement_index )  { 
@@ -809,36 +822,64 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
809822            kind :  TerminatorKind :: Call  {  fn_span,  from_hir_call,  .. } ,  ..
810823        } )  = & self . body [ location. block ] . terminator 
811824        { 
812-             let  method_did  = if  let  Some ( method_did )  =
825+             let  ( method_did,  method_substs )   = if  let  Some ( info )  =
813826                crate :: util:: find_self_call ( self . infcx . tcx ,  & self . body ,  target_temp,  location. block ) 
814827            { 
815-                 method_did 
828+                 info 
816829            }  else  { 
817830                return  normal_ret; 
818831            } ; 
819832
820833            let  tcx = self . infcx . tcx ; 
821- 
822834            let  parent = tcx. parent ( method_did) ; 
823835            let  is_fn_once = parent == tcx. lang_items ( ) . fn_once_trait ( ) ; 
824836            let  is_operator = !from_hir_call
825837                && parent. map_or ( false ,  |p| tcx. lang_items ( ) . group ( LangItemGroup :: Op ) . contains ( & p) ) ; 
838+             let  is_deref = !from_hir_call && tcx. is_diagnostic_item ( sym:: deref_method,  method_did) ; 
826839            let  fn_call_span = * fn_span; 
827840
828841            let  self_arg = tcx. fn_arg_names ( method_did) [ 0 ] ; 
829842
843+             debug ! ( 
844+                 "terminator = {:?} from_hir_call={:?}" , 
845+                 self . body[ location. block] . terminator,  from_hir_call
846+             ) ; 
847+ 
848+             // Check for a 'special' use of 'self' - 
849+             // an FnOnce call, an operator (e.g. `<<`), or a 
850+             // deref coercion. 
830851            let  kind = if  is_fn_once { 
831-                 FnSelfUseKind :: FnOnceCall 
852+                 Some ( FnSelfUseKind :: FnOnceCall ) 
832853            }  else  if  is_operator { 
833-                 FnSelfUseKind :: Operator  {  self_arg } 
854+                 Some ( FnSelfUseKind :: Operator  {  self_arg } ) 
855+             }  else  if  is_deref { 
856+                 let  deref_target =
857+                     tcx. get_diagnostic_item ( sym:: deref_target) . and_then ( |deref_target| { 
858+                         Instance :: resolve ( tcx,  self . param_env ,  deref_target,  method_substs) 
859+                             . transpose ( ) 
860+                     } ) ; 
861+                 if  let  Some ( Ok ( instance) )  = deref_target { 
862+                     let  deref_target_ty = instance. ty ( tcx,  self . param_env ) ; 
863+                     Some ( FnSelfUseKind :: DerefCoercion  { 
864+                         deref_target :  tcx. def_span ( instance. def_id ( ) ) , 
865+                         deref_target_ty, 
866+                     } ) 
867+                 }  else  { 
868+                     None 
869+                 } 
834870            }  else  { 
871+                 None 
872+             } ; 
873+ 
874+             let  kind = kind. unwrap_or_else ( || { 
875+                 // This isn't a 'special' use of `self` 
835876                debug ! ( "move_spans: method_did={:?}, fn_call_span={:?}" ,  method_did,  fn_call_span) ; 
836877                let  implicit_into_iter = matches ! ( 
837878                    fn_call_span. desugaring_kind( ) , 
838879                    Some ( DesugaringKind :: ForLoop ( ForLoopLoc :: IntoIter ) ) 
839880                ) ; 
840881                FnSelfUseKind :: Normal  {  self_arg,  implicit_into_iter } 
841-             } ; 
882+             } ) ; 
842883
843884            return  FnSelfUse  { 
844885                var_span :  stmt. source_info . span , 
@@ -859,7 +900,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
859900     /// and its usage of the local assigned at `location`. 
860901     /// This is done by searching in statements succeeding `location` 
861902     /// and originating from `maybe_closure_span`. 
862-      pub ( super )  fn  borrow_spans ( & self ,  use_span :  Span ,  location :  Location )  -> UseSpans  { 
903+      pub ( super )  fn  borrow_spans ( & self ,  use_span :  Span ,  location :  Location )  -> UseSpans < ' tcx >  { 
863904        use  self :: UseSpans :: * ; 
864905        debug ! ( "borrow_spans: use_span={:?} location={:?}" ,  use_span,  location) ; 
865906
@@ -963,7 +1004,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
9631004
9641005    /// Helper to retrieve span(s) of given borrow from the current MIR 
9651006     /// representation 
966-      pub ( super )  fn  retrieve_borrow_spans ( & self ,  borrow :  & BorrowData < ' _ > )  -> UseSpans  { 
1007+      pub ( super )  fn  retrieve_borrow_spans ( & self ,  borrow :  & BorrowData < ' _ > )  -> UseSpans < ' tcx >  { 
9671008        let  span = self . body . source_info ( borrow. reserve_location ) . span ; 
9681009        self . borrow_spans ( span,  borrow. reserve_location ) 
9691010    } 
0 commit comments