@@ -11,7 +11,7 @@ use rustc_middle::mir::{
11
11
PlaceRef , ProjectionElem , Rvalue , Statement , StatementKind , Terminator , TerminatorKind ,
12
12
} ;
13
13
use rustc_middle:: ty:: print:: Print ;
14
- use rustc_middle:: ty:: { self , DefIdTree , Ty , TyCtxt } ;
14
+ use rustc_middle:: ty:: { self , DefIdTree , Instance , Ty , TyCtxt } ;
15
15
use rustc_span:: {
16
16
hygiene:: { DesugaringKind , ForLoopLoc } ,
17
17
symbol:: sym,
@@ -538,7 +538,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
538
538
539
539
/// The span(s) associated to a use of a place.
540
540
#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
541
- pub ( super ) enum UseSpans {
541
+ pub ( super ) enum UseSpans < ' tcx > {
542
542
/// The access is caused by capturing a variable for a closure.
543
543
ClosureUse {
544
544
/// This is true if the captured variable was from a generator.
@@ -558,7 +558,7 @@ pub(super) enum UseSpans {
558
558
fn_call_span : Span ,
559
559
/// The definition span of the method being called
560
560
fn_span : Span ,
561
- kind : FnSelfUseKind ,
561
+ kind : FnSelfUseKind < ' tcx > ,
562
562
} ,
563
563
/// This access is caused by a `match` or `if let` pattern.
564
564
PatUse ( Span ) ,
@@ -567,31 +567,44 @@ pub(super) enum UseSpans {
567
567
}
568
568
569
569
#[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
570
- pub ( super ) enum FnSelfUseKind {
570
+ pub ( super ) enum FnSelfUseKind < ' tcx > {
571
571
/// A normal method call of the form `receiver.foo(a, b, c)`
572
572
Normal { self_arg : Ident , implicit_into_iter : bool } ,
573
573
/// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
574
574
FnOnceCall ,
575
575
/// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
576
576
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
+ } ,
577
584
}
578
585
579
- impl UseSpans {
586
+ impl UseSpans < ' _ > {
580
587
pub ( super ) fn args_or_use ( self ) -> Span {
581
588
match self {
582
589
UseSpans :: ClosureUse { args_span : span, .. }
583
590
| UseSpans :: PatUse ( span)
584
- | UseSpans :: FnSelfUse { var_span : span, .. }
585
591
| 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,
586
596
}
587
597
}
588
598
589
599
pub ( super ) fn var_or_use ( self ) -> Span {
590
600
match self {
591
601
UseSpans :: ClosureUse { var_span : span, .. }
592
602
| UseSpans :: PatUse ( span)
593
- | UseSpans :: FnSelfUse { var_span : span, .. }
594
603
| 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,
595
608
}
596
609
}
597
610
@@ -754,7 +767,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
754
767
& self ,
755
768
moved_place : PlaceRef < ' tcx > , // Could also be an upvar.
756
769
location : Location ,
757
- ) -> UseSpans {
770
+ ) -> UseSpans < ' tcx > {
758
771
use self :: UseSpans :: * ;
759
772
760
773
let stmt = match self . body [ location. block ] . statements . get ( location. statement_index ) {
@@ -809,36 +822,64 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
809
822
kind : TerminatorKind :: Call { fn_span, from_hir_call, .. } , ..
810
823
} ) = & self . body [ location. block ] . terminator
811
824
{
812
- let method_did = if let Some ( method_did ) =
825
+ let ( method_did, method_substs ) = if let Some ( info ) =
813
826
crate :: util:: find_self_call ( self . infcx . tcx , & self . body , target_temp, location. block )
814
827
{
815
- method_did
828
+ info
816
829
} else {
817
830
return normal_ret;
818
831
} ;
819
832
820
833
let tcx = self . infcx . tcx ;
821
-
822
834
let parent = tcx. parent ( method_did) ;
823
835
let is_fn_once = parent == tcx. lang_items ( ) . fn_once_trait ( ) ;
824
836
let is_operator = !from_hir_call
825
837
&& 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) ;
826
839
let fn_call_span = * fn_span;
827
840
828
841
let self_arg = tcx. fn_arg_names ( method_did) [ 0 ] ;
829
842
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.
830
851
let kind = if is_fn_once {
831
- FnSelfUseKind :: FnOnceCall
852
+ Some ( FnSelfUseKind :: FnOnceCall )
832
853
} 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
+ }
834
870
} else {
871
+ None
872
+ } ;
873
+
874
+ let kind = kind. unwrap_or_else ( || {
875
+ // This isn't a 'special' use of `self`
835
876
debug ! ( "move_spans: method_did={:?}, fn_call_span={:?}" , method_did, fn_call_span) ;
836
877
let implicit_into_iter = matches ! (
837
878
fn_call_span. desugaring_kind( ) ,
838
879
Some ( DesugaringKind :: ForLoop ( ForLoopLoc :: IntoIter ) )
839
880
) ;
840
881
FnSelfUseKind :: Normal { self_arg, implicit_into_iter }
841
- } ;
882
+ } ) ;
842
883
843
884
return FnSelfUse {
844
885
var_span : stmt. source_info . span ,
@@ -859,7 +900,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
859
900
/// and its usage of the local assigned at `location`.
860
901
/// This is done by searching in statements succeeding `location`
861
902
/// 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 > {
863
904
use self :: UseSpans :: * ;
864
905
debug ! ( "borrow_spans: use_span={:?} location={:?}" , use_span, location) ;
865
906
@@ -963,7 +1004,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
963
1004
964
1005
/// Helper to retrieve span(s) of given borrow from the current MIR
965
1006
/// representation
966
- pub ( super ) fn retrieve_borrow_spans ( & self , borrow : & BorrowData < ' _ > ) -> UseSpans {
1007
+ pub ( super ) fn retrieve_borrow_spans ( & self , borrow : & BorrowData < ' _ > ) -> UseSpans < ' tcx > {
967
1008
let span = self . body . source_info ( borrow. reserve_location ) . span ;
968
1009
self . borrow_spans ( span, borrow. reserve_location )
969
1010
}
0 commit comments