@@ -128,7 +128,7 @@ pub enum PointerKind {
128128#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
129129pub enum InteriorKind {
130130 InteriorField ( FieldName ) ,
131- InteriorElement ( ElementKind ) ,
131+ InteriorElement ( InteriorOffsetKind , ElementKind ) ,
132132}
133133
134134#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
@@ -137,6 +137,12 @@ pub enum FieldName {
137137 PositionalField ( uint )
138138}
139139
140+ #[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
141+ pub enum InteriorOffsetKind {
142+ Index , // e.g. `array_expr[index_expr]`
143+ Pattern , // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
144+ }
145+
140146#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
141147pub enum ElementKind {
142148 VecElement ,
@@ -196,10 +202,12 @@ pub enum deref_kind {
196202 deref_interior( InteriorKind ) ,
197203}
198204
205+ type DerefKindContext = Option < InteriorOffsetKind > ;
206+
199207// Categorizes a derefable type. Note that we include vectors and strings as
200208// derefable (we model an index as the combination of a deref and then a
201209// pointer adjustment).
202- pub fn deref_kind ( t : Ty ) -> McResult < deref_kind > {
210+ fn deref_kind ( t : Ty , context : DerefKindContext ) -> McResult < deref_kind > {
203211 match t. sty {
204212 ty:: ty_uniq( _) => {
205213 Ok ( deref_ptr ( Unique ) )
@@ -220,7 +228,12 @@ pub fn deref_kind(t: Ty) -> McResult<deref_kind> {
220228 }
221229
222230 ty:: ty_vec( _, _) | ty:: ty_str => {
223- Ok ( deref_interior ( InteriorElement ( element_kind ( t) ) ) )
231+ // no deref of indexed content without supplying InteriorOffsetKind
232+ if let Some ( context) = context {
233+ Ok ( deref_interior ( InteriorElement ( context, element_kind ( t) ) ) )
234+ } else {
235+ Err ( ( ) )
236+ }
224237 }
225238
226239 _ => Err ( ( ) ) ,
@@ -455,7 +468,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
455468 autoderefs,
456469 cmt. repr( self . tcx( ) ) ) ;
457470 for deref in 1 ..autoderefs + 1 {
458- cmt = try!( self . cat_deref ( expr, cmt, deref) ) ;
471+ cmt = try!( self . cat_deref ( expr, cmt, deref, None ) ) ;
459472 }
460473 return Ok ( cmt) ;
461474 }
@@ -467,7 +480,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
467480 match expr. node {
468481 ast:: ExprUnary ( ast:: UnDeref , ref e_base) => {
469482 let base_cmt = try!( self . cat_expr ( & * * e_base) ) ;
470- self . cat_deref ( expr, base_cmt, 0 )
483+ self . cat_deref ( expr, base_cmt, 0 , None )
471484 }
472485
473486 ast:: ExprField ( ref base, f_name) => {
@@ -486,6 +499,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
486499
487500 ast:: ExprIndex ( ref base, _) => {
488501 let method_call = ty:: MethodCall :: expr ( expr. id ( ) ) ;
502+ let context = InteriorOffsetKind :: Index ;
489503 match self . typer . node_method_ty ( method_call) {
490504 Some ( method_ty) => {
491505 // If this is an index implemented by a method call, then it
@@ -507,10 +521,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
507521 // is an rvalue. That is what we will be
508522 // dereferencing.
509523 let base_cmt = self . cat_rvalue_node ( expr. id ( ) , expr. span ( ) , ret_ty) ;
510- self . cat_deref_common ( expr, base_cmt, 1 , elem_ty, true )
524+ self . cat_deref_common ( expr, base_cmt, 1 , elem_ty, Some ( context ) , true )
511525 }
512526 None => {
513- self . cat_index ( expr, try!( self . cat_expr ( & * * base) ) )
527+ self . cat_index ( expr, try!( self . cat_expr ( & * * base) ) , context )
514528 }
515529 }
516530 }
@@ -854,7 +868,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
854868 fn cat_deref < N : ast_node > ( & self ,
855869 node : & N ,
856870 base_cmt : cmt < ' tcx > ,
857- deref_cnt : uint )
871+ deref_cnt : uint ,
872+ deref_context : DerefKindContext )
858873 -> McResult < cmt < ' tcx > > {
859874 let adjustment = match self . typer . adjustments ( ) . borrow ( ) . get ( & node. id ( ) ) {
860875 Some ( adj) if ty:: adjust_is_object ( adj) => ty:: AutoObject ,
@@ -882,7 +897,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
882897 } ;
883898 let base_cmt_ty = base_cmt. ty ;
884899 match ty:: deref ( base_cmt_ty, true ) {
885- Some ( mt) => self . cat_deref_common ( node, base_cmt, deref_cnt, mt. ty ,
900+ Some ( mt) => self . cat_deref_common ( node, base_cmt, deref_cnt,
901+ mt. ty ,
902+ deref_context,
886903 /* implicit: */ false ) ,
887904 None => {
888905 debug ! ( "Explicit deref of non-derefable type: {}" ,
@@ -897,10 +914,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
897914 base_cmt : cmt < ' tcx > ,
898915 deref_cnt : uint ,
899916 deref_ty : Ty < ' tcx > ,
917+ deref_context : DerefKindContext ,
900918 implicit : bool )
901919 -> McResult < cmt < ' tcx > >
902920 {
903- let ( m, cat) = match try!( deref_kind ( base_cmt. ty ) ) {
921+ let ( m, cat) = match try!( deref_kind ( base_cmt. ty , deref_context ) ) {
904922 deref_ptr( ptr) => {
905923 let ptr = if implicit {
906924 match ptr {
@@ -932,7 +950,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
932950
933951 pub fn cat_index < N : ast_node > ( & self ,
934952 elt : & N ,
935- mut base_cmt : cmt < ' tcx > )
953+ mut base_cmt : cmt < ' tcx > ,
954+ context : InteriorOffsetKind )
936955 -> McResult < cmt < ' tcx > > {
937956 //! Creates a cmt for an indexing operation (`[]`).
938957 //!
@@ -974,18 +993,21 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
974993 } ;
975994
976995 let m = base_cmt. mutbl . inherit ( ) ;
977- return Ok ( interior ( elt, base_cmt. clone ( ) , base_cmt. ty , m, element_ty) ) ;
996+ return Ok ( interior ( elt, base_cmt. clone ( ) , base_cmt. ty ,
997+ m, context, element_ty) ) ;
978998
979999 fn interior < ' tcx , N : ast_node > ( elt : & N ,
9801000 of_cmt : cmt < ' tcx > ,
9811001 vec_ty : Ty < ' tcx > ,
9821002 mutbl : MutabilityCategory ,
1003+ context : InteriorOffsetKind ,
9831004 element_ty : Ty < ' tcx > ) -> cmt < ' tcx >
9841005 {
1006+ let interior_elem = InteriorElement ( context, element_kind ( vec_ty) ) ;
9851007 Rc :: new ( cmt_ {
9861008 id : elt. id ( ) ,
9871009 span : elt. span ( ) ,
988- cat : cat_interior ( of_cmt, InteriorElement ( element_kind ( vec_ty ) ) ) ,
1010+ cat : cat_interior ( of_cmt, interior_elem ) ,
9891011 mutbl : mutbl,
9901012 ty : element_ty,
9911013 note : NoteNone
@@ -997,10 +1019,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
9971019 // underlying vec.
9981020 fn deref_vec < N : ast_node > ( & self ,
9991021 elt : & N ,
1000- base_cmt : cmt < ' tcx > )
1022+ base_cmt : cmt < ' tcx > ,
1023+ context : InteriorOffsetKind )
10011024 -> McResult < cmt < ' tcx > >
10021025 {
1003- match try!( deref_kind ( base_cmt. ty ) ) {
1026+ match try!( deref_kind ( base_cmt. ty , Some ( context ) ) ) {
10041027 deref_ptr( ptr) => {
10051028 // for unique ptrs, we inherit mutability from the
10061029 // owning reference.
@@ -1041,7 +1064,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
10411064 let ( slice_mutbl, slice_r) = vec_slice_info ( self . tcx ( ) ,
10421065 slice_pat,
10431066 slice_ty) ;
1044- let cmt_slice = try!( self . cat_index ( slice_pat, try!( self . deref_vec ( slice_pat, vec_cmt) ) ) ) ;
1067+ let context = InteriorOffsetKind :: Pattern ;
1068+ let cmt_vec = try!( self . deref_vec ( slice_pat, vec_cmt, context) ) ;
1069+ let cmt_slice = try!( self . cat_index ( slice_pat, cmt_vec, context) ) ;
10451070 return Ok ( ( cmt_slice, slice_mutbl, slice_r) ) ;
10461071
10471072 /// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
@@ -1253,12 +1278,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
12531278 // box p1, &p1, &mut p1. we can ignore the mutability of
12541279 // PatRegion since that information is already contained
12551280 // in the type.
1256- let subcmt = try!( self . cat_deref ( pat, cmt, 0 ) ) ;
1281+ let subcmt = try!( self . cat_deref ( pat, cmt, 0 , None ) ) ;
12571282 try!( self . cat_pattern_ ( subcmt, & * * subpat, op) ) ;
12581283 }
12591284
12601285 ast:: PatVec ( ref before, ref slice, ref after) => {
1261- let elt_cmt = try!( self . cat_index ( pat, try!( self . deref_vec ( pat, cmt) ) ) ) ;
1286+ let context = InteriorOffsetKind :: Pattern ;
1287+ let vec_cmt = try!( self . deref_vec ( pat, cmt, context) ) ;
1288+ let elt_cmt = try!( self . cat_index ( pat, vec_cmt, context) ) ;
12621289 for before_pat in before {
12631290 try!( self . cat_pattern_ ( elt_cmt. clone ( ) , & * * before_pat, op) ) ;
12641291 }
@@ -1455,10 +1482,18 @@ impl<'tcx> cmt_<'tcx> {
14551482 cat_interior( _, InteriorField ( PositionalField ( _) ) ) => {
14561483 "anonymous field" . to_string ( )
14571484 }
1458- cat_interior( _, InteriorElement ( VecElement ) ) |
1459- cat_interior( _, InteriorElement ( OtherElement ) ) => {
1485+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Index ,
1486+ VecElement ) ) |
1487+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Index ,
1488+ OtherElement ) ) => {
14601489 "indexed content" . to_string ( )
14611490 }
1491+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1492+ VecElement ) ) |
1493+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1494+ OtherElement ) ) => {
1495+ "pattern-bound indexed content" . to_string ( )
1496+ }
14621497 cat_upvar( ref var) => {
14631498 var. user_string ( tcx)
14641499 }
@@ -1546,7 +1581,7 @@ impl<'tcx> Repr<'tcx> for InteriorKind {
15461581 token:: get_name ( fld) . to_string ( )
15471582 }
15481583 InteriorField ( PositionalField ( i) ) => format ! ( "#{}" , i) ,
1549- InteriorElement ( _ ) => "[]" . to_string ( ) ,
1584+ InteriorElement ( .. ) => "[]" . to_string ( ) ,
15501585 }
15511586 }
15521587}
0 commit comments