6363pub use self :: PointerKind :: * ;
6464pub use self :: InteriorKind :: * ;
6565pub use self :: FieldName :: * ;
66- pub use self :: ElementKind :: * ;
6766pub use self :: MutabilityCategory :: * ;
6867pub use self :: AliasableReason :: * ;
6968pub use self :: Note :: * ;
@@ -129,7 +128,7 @@ pub enum PointerKind<'tcx> {
129128#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
130129pub enum InteriorKind {
131130 InteriorField ( FieldName ) ,
132- InteriorElement ( InteriorOffsetKind , ElementKind ) ,
131+ InteriorElement ( InteriorOffsetKind ) ,
133132}
134133
135134#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
@@ -144,12 +143,6 @@ pub enum InteriorOffsetKind {
144143 Pattern , // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
145144}
146145
147- #[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
148- pub enum ElementKind {
149- VecElement ,
150- OtherElement ,
151- }
152-
153146#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
154147pub enum MutabilityCategory {
155148 McImmutable , // Immutable.
@@ -492,7 +485,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
492485 debug ! ( "cat_expr: autoderefs={:?}, cmt={:?}" ,
493486 autoderefs, cmt) ;
494487 for & overloaded in autoderefs {
495- cmt = self . cat_deref ( expr, cmt, overloaded) ?;
488+ if let Some ( method) = overloaded {
489+ cmt = self . cat_overloaded_autoderef ( expr, method) ?;
490+ } else {
491+ cmt = self . cat_deref ( expr, cmt, false ) ?;
492+ }
496493 }
497494 return Ok ( cmt) ;
498495 }
@@ -518,10 +515,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
518515 let expr_ty = self . expr_ty ( expr) ?;
519516 match expr. node {
520517 hir:: ExprUnary ( hir:: UnDeref , ref e_base) => {
521- let base_cmt = self . cat_expr ( & e_base) ?;
522- let method = self . infcx . tables . borrow ( ) . method_map
523- . get ( & expr. id ) . cloned ( ) ;
524- self . cat_deref ( expr, base_cmt, method)
518+ if self . infcx . tables . borrow ( ) . is_method_call ( expr. id ) {
519+ self . cat_overloaded_lvalue ( expr, e_base, false )
520+ } else {
521+ let base_cmt = self . cat_expr ( & e_base) ?;
522+ self . cat_deref ( expr, base_cmt, false )
523+ }
525524 }
526525
527526 hir:: ExprField ( ref base, f_name) => {
@@ -539,33 +538,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
539538 }
540539
541540 hir:: ExprIndex ( ref base, _) => {
542- let method = self . infcx . tables . borrow ( ) . method_map . get ( & expr. id ( ) ) . cloned ( ) ;
543- match method {
544- Some ( method) => {
545- // If this is an index implemented by a method call, then it
546- // will include an implicit deref of the result.
547- let ret_ty = self . overloaded_method_return_ty ( method) ;
548-
549- // The index method always returns an `&T`, so
550- // dereference it to find the result type.
551- let elem_ty = match ret_ty. sty {
552- ty:: TyRef ( _, mt) => mt. ty ,
553- _ => {
554- debug ! ( "cat_expr_unadjusted: return type of overloaded index is {:?}?" ,
555- ret_ty) ;
556- return Err ( ( ) ) ;
557- }
558- } ;
559-
560- // The call to index() returns a `&T` value, which
561- // is an rvalue. That is what we will be
562- // dereferencing.
563- let base_cmt = self . cat_rvalue_node ( expr. id ( ) , expr. span ( ) , ret_ty) ;
564- Ok ( self . cat_deref_common ( expr, base_cmt, elem_ty, true ) )
565- }
566- None => {
567- self . cat_index ( expr, self . cat_expr ( & base) ?, InteriorOffsetKind :: Index )
568- }
541+ if self . infcx . tables . borrow ( ) . is_method_call ( expr. id ( ) ) {
542+ // If this is an index implemented by a method call, then it
543+ // will include an implicit deref of the result.
544+ // The call to index() returns a `&T` value, which
545+ // is an rvalue. That is what we will be
546+ // dereferencing.
547+ self . cat_overloaded_lvalue ( expr, base, true )
548+ } else {
549+ let base_cmt = self . cat_expr ( & base) ?;
550+ self . cat_index ( expr, base_cmt, expr_ty, InteriorOffsetKind :: Index )
569551 }
570552 }
571553
@@ -924,50 +906,71 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
924906 ret
925907 }
926908
909+ fn cat_overloaded_lvalue ( & self ,
910+ expr : & hir:: Expr ,
911+ base : & hir:: Expr ,
912+ implicit : bool )
913+ -> McResult < cmt < ' tcx > > {
914+ debug ! ( "cat_overloaded_lvalue: implicit={}" , implicit) ;
915+
916+ // Reconstruct the output assuming it's a reference with the
917+ // same region and mutability as the receiver. This holds for
918+ // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
919+ let lvalue_ty = self . expr_ty ( expr) ?;
920+ let base_ty = self . expr_ty_adjusted ( base) ?;
921+
922+ let ( region, mutbl) = match base_ty. sty {
923+ ty:: TyRef ( region, mt) => ( region, mt. mutbl ) ,
924+ _ => {
925+ span_bug ! ( expr. span, "cat_overloaded_lvalue: base is not a reference" )
926+ }
927+ } ;
928+ let ref_ty = self . tcx ( ) . mk_ref ( region, ty:: TypeAndMut {
929+ ty : lvalue_ty,
930+ mutbl,
931+ } ) ;
932+
933+ let base_cmt = self . cat_rvalue_node ( expr. id , expr. span , ref_ty) ;
934+ self . cat_deref ( expr, base_cmt, implicit)
935+ }
936+
937+ pub fn cat_overloaded_autoderef ( & self ,
938+ expr : & hir:: Expr ,
939+ method : ty:: MethodCallee < ' tcx > )
940+ -> McResult < cmt < ' tcx > > {
941+ debug ! ( "cat_overloaded_autoderef: method={:?}" , method) ;
942+
943+ let ref_ty = method. sig . output ( ) ;
944+ let ref_ty = self . infcx . resolve_type_vars_if_possible ( & ref_ty) ;
945+ let base_cmt = self . cat_rvalue_node ( expr. id , expr. span , ref_ty) ;
946+ self . cat_deref ( expr, base_cmt, false )
947+ }
948+
927949 pub fn cat_deref < N : ast_node > ( & self ,
928950 node : & N ,
929951 base_cmt : cmt < ' tcx > ,
930- overloaded : Option < ty :: MethodCallee < ' tcx > > )
952+ implicit : bool )
931953 -> McResult < cmt < ' tcx > > {
932- debug ! ( "cat_deref: overloaded ={:?}" , overloaded ) ;
954+ debug ! ( "cat_deref: base_cmt ={:?}" , base_cmt ) ;
933955
934- let base_cmt = match overloaded {
935- Some ( method) => {
936- let ref_ty = self . overloaded_method_return_ty ( method) ;
937- self . cat_rvalue_node ( node. id ( ) , node. span ( ) , ref_ty)
938- }
939- None => base_cmt
940- } ;
941956 let base_cmt_ty = base_cmt. ty ;
942- match base_cmt_ty. builtin_deref ( true , ty:: NoPreference ) {
943- Some ( mt) => {
944- let ret = self . cat_deref_common ( node, base_cmt, mt. ty , false ) ;
945- debug ! ( "cat_deref ret {:?}" , ret) ;
946- Ok ( ret)
947- }
957+ let deref_ty = match base_cmt_ty. builtin_deref ( true , ty:: NoPreference ) {
958+ Some ( mt) => mt. ty ,
948959 None => {
949960 debug ! ( "Explicit deref of non-derefable type: {:?}" ,
950961 base_cmt_ty) ;
951962 return Err ( ( ) ) ;
952963 }
953- }
954- }
964+ } ;
955965
956- fn cat_deref_common < N : ast_node > ( & self ,
957- node : & N ,
958- base_cmt : cmt < ' tcx > ,
959- deref_ty : Ty < ' tcx > ,
960- implicit : bool )
961- -> cmt < ' tcx >
962- {
963966 let ptr = match base_cmt. ty . sty {
964967 ty:: TyAdt ( def, ..) if def. is_box ( ) => Unique ,
965968 ty:: TyRawPtr ( ref mt) => UnsafePtr ( mt. mutbl ) ,
966969 ty:: TyRef ( r, mt) => {
967970 let bk = ty:: BorrowKind :: from_mutbl ( mt. mutbl ) ;
968971 if implicit { Implicit ( bk, r) } else { BorrowedPtr ( bk, r) }
969972 }
970- ref ty => bug ! ( "unexpected type in cat_deref_common : {:?}" , ty)
973+ ref ty => bug ! ( "unexpected type in cat_deref : {:?}" , ty)
971974 } ;
972975 let ret = Rc :: new ( cmt_ {
973976 id : node. id ( ) ,
@@ -978,15 +981,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
978981 ty : deref_ty,
979982 note : NoteNone
980983 } ) ;
981- debug ! ( "cat_deref_common ret {:?}" , ret) ;
982- ret
984+ debug ! ( "cat_deref ret {:?}" , ret) ;
985+ Ok ( ret)
983986 }
984987
985- pub fn cat_index < N : ast_node > ( & self ,
986- elt : & N ,
987- mut base_cmt : cmt < ' tcx > ,
988- context : InteriorOffsetKind )
989- -> McResult < cmt < ' tcx > > {
988+ fn cat_index < N : ast_node > ( & self ,
989+ elt : & N ,
990+ base_cmt : cmt < ' tcx > ,
991+ element_ty : Ty < ' tcx > ,
992+ context : InteriorOffsetKind )
993+ -> McResult < cmt < ' tcx > > {
990994 //! Creates a cmt for an indexing operation (`[]`).
991995 //!
992996 //! One subtle aspect of indexing that may not be
@@ -1004,29 +1008,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
10041008 //! - `elt`: the AST node being indexed
10051009 //! - `base_cmt`: the cmt of `elt`
10061010
1007- let method = self . infcx . tables . borrow ( ) . method_map . get ( & elt. id ( ) ) . cloned ( ) ;
1008- let ( element_ty, element_kind) = match method {
1009- Some ( method) => {
1010- let ref_ty = self . overloaded_method_return_ty ( method) ;
1011- base_cmt = self . cat_rvalue_node ( elt. id ( ) , elt. span ( ) , ref_ty) ;
1012-
1013- ( ref_ty. builtin_deref ( false , ty:: NoPreference ) . unwrap ( ) . ty ,
1014- ElementKind :: OtherElement )
1015- }
1016- None => {
1017- match base_cmt. ty . builtin_index ( ) {
1018- Some ( ty) => ( ty, ElementKind :: VecElement ) ,
1019- None => {
1020- debug ! ( "Explicit index of non-indexable type {:?}" , base_cmt) ;
1021- return Err ( ( ) ) ;
1022- }
1023- }
1024- }
1025- } ;
1026-
1027- let interior_elem = InteriorElement ( context, element_kind) ;
1011+ let interior_elem = InteriorElement ( context) ;
10281012 let ret =
1029- self . cat_imm_interior ( elt, base_cmt. clone ( ) , element_ty, interior_elem) ;
1013+ self . cat_imm_interior ( elt, base_cmt, element_ty, interior_elem) ;
10301014 debug ! ( "cat_index ret {:?}" , ret) ;
10311015 return Ok ( ret) ;
10321016 }
@@ -1216,15 +1200,20 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
12161200 // box p1, &p1, &mut p1. we can ignore the mutability of
12171201 // PatKind::Ref since that information is already contained
12181202 // in the type.
1219- let method = self . infcx . tables . borrow ( ) . method_map
1220- . get ( & pat. id ) . cloned ( ) ;
1221- let subcmt = self . cat_deref ( pat, cmt, method) ?;
1203+ let subcmt = self . cat_deref ( pat, cmt, false ) ?;
12221204 self . cat_pattern_ ( subcmt, & subpat, op) ?;
12231205 }
12241206
12251207 PatKind :: Slice ( ref before, ref slice, ref after) => {
1208+ let element_ty = match cmt. ty . builtin_index ( ) {
1209+ Some ( ty) => ty,
1210+ None => {
1211+ debug ! ( "Explicit index of non-indexable type {:?}" , cmt) ;
1212+ return Err ( ( ) ) ;
1213+ }
1214+ } ;
12261215 let context = InteriorOffsetKind :: Pattern ;
1227- let elt_cmt = self . cat_index ( pat, cmt, context) ?;
1216+ let elt_cmt = self . cat_index ( pat, cmt, element_ty , context) ?;
12281217 for before_pat in before {
12291218 self . cat_pattern_ ( elt_cmt. clone ( ) , & before_pat, op) ?;
12301219 }
@@ -1244,16 +1233,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
12441233
12451234 Ok ( ( ) )
12461235 }
1247-
1248- fn overloaded_method_return_ty ( & self ,
1249- method : ty:: MethodCallee < ' tcx > )
1250- -> Ty < ' tcx >
1251- {
1252- // When we process an overloaded `*` or `[]` etc, we often
1253- // need to extract the return type of the method.
1254- let ret_ty = method. sig . output ( ) ;
1255- self . infcx . resolve_type_vars_if_possible ( & ret_ty)
1256- }
12571236}
12581237
12591238#[ derive( Clone , Debug ) ]
@@ -1401,16 +1380,10 @@ impl<'tcx> cmt_<'tcx> {
14011380 Categorization :: Interior ( _, InteriorField ( PositionalField ( _) ) ) => {
14021381 "anonymous field" . to_string ( )
14031382 }
1404- Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Index ,
1405- VecElement ) ) |
1406- Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Index ,
1407- OtherElement ) ) => {
1383+ Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Index ) ) => {
14081384 "indexed content" . to_string ( )
14091385 }
1410- Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1411- VecElement ) ) |
1412- Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1413- OtherElement ) ) => {
1386+ Categorization :: Interior ( _, InteriorElement ( InteriorOffsetKind :: Pattern ) ) => {
14141387 "pattern-bound indexed content" . to_string ( )
14151388 }
14161389 Categorization :: Upvar ( ref var) => {
0 commit comments