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