@@ -128,7 +128,7 @@ pub enum PointerKind {
128
128
#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
129
129
pub enum InteriorKind {
130
130
InteriorField ( FieldName ) ,
131
- InteriorElement ( ElementKind ) ,
131
+ InteriorElement ( InteriorOffsetKind , ElementKind ) ,
132
132
}
133
133
134
134
#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
@@ -137,6 +137,12 @@ pub enum FieldName {
137
137
PositionalField ( uint )
138
138
}
139
139
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
+
140
146
#[ derive( Clone , Copy , PartialEq , Eq , Hash , Debug ) ]
141
147
pub enum ElementKind {
142
148
VecElement ,
@@ -196,10 +202,12 @@ pub enum deref_kind {
196
202
deref_interior( InteriorKind ) ,
197
203
}
198
204
205
+ type DerefKindContext = Option < InteriorOffsetKind > ;
206
+
199
207
// Categorizes a derefable type. Note that we include vectors and strings as
200
208
// derefable (we model an index as the combination of a deref and then a
201
209
// pointer adjustment).
202
- pub fn deref_kind ( t : Ty ) -> McResult < deref_kind > {
210
+ fn deref_kind ( t : Ty , context : DerefKindContext ) -> McResult < deref_kind > {
203
211
match t. sty {
204
212
ty:: ty_uniq( _) => {
205
213
Ok ( deref_ptr ( Unique ) )
@@ -220,7 +228,12 @@ pub fn deref_kind(t: Ty) -> McResult<deref_kind> {
220
228
}
221
229
222
230
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
+ }
224
237
}
225
238
226
239
_ => Err ( ( ) ) ,
@@ -455,7 +468,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
455
468
autoderefs,
456
469
cmt. repr( self . tcx( ) ) ) ;
457
470
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 ) ) ;
459
472
}
460
473
return Ok ( cmt) ;
461
474
}
@@ -467,7 +480,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
467
480
match expr. node {
468
481
ast:: ExprUnary ( ast:: UnDeref , ref e_base) => {
469
482
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 )
471
484
}
472
485
473
486
ast:: ExprField ( ref base, f_name) => {
@@ -486,6 +499,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
486
499
487
500
ast:: ExprIndex ( ref base, _) => {
488
501
let method_call = ty:: MethodCall :: expr ( expr. id ( ) ) ;
502
+ let context = InteriorOffsetKind :: Index ;
489
503
match self . typer . node_method_ty ( method_call) {
490
504
Some ( method_ty) => {
491
505
// 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> {
507
521
// is an rvalue. That is what we will be
508
522
// dereferencing.
509
523
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 )
511
525
}
512
526
None => {
513
- self . cat_index ( expr, try!( self . cat_expr ( & * * base) ) )
527
+ self . cat_index ( expr, try!( self . cat_expr ( & * * base) ) , context )
514
528
}
515
529
}
516
530
}
@@ -854,7 +868,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
854
868
fn cat_deref < N : ast_node > ( & self ,
855
869
node : & N ,
856
870
base_cmt : cmt < ' tcx > ,
857
- deref_cnt : uint )
871
+ deref_cnt : uint ,
872
+ deref_context : DerefKindContext )
858
873
-> McResult < cmt < ' tcx > > {
859
874
let adjustment = match self . typer . adjustments ( ) . borrow ( ) . get ( & node. id ( ) ) {
860
875
Some ( adj) if ty:: adjust_is_object ( adj) => ty:: AutoObject ,
@@ -882,7 +897,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
882
897
} ;
883
898
let base_cmt_ty = base_cmt. ty ;
884
899
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,
886
903
/* implicit: */ false ) ,
887
904
None => {
888
905
debug ! ( "Explicit deref of non-derefable type: {}" ,
@@ -897,10 +914,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
897
914
base_cmt : cmt < ' tcx > ,
898
915
deref_cnt : uint ,
899
916
deref_ty : Ty < ' tcx > ,
917
+ deref_context : DerefKindContext ,
900
918
implicit : bool )
901
919
-> McResult < cmt < ' tcx > >
902
920
{
903
- let ( m, cat) = match try!( deref_kind ( base_cmt. ty ) ) {
921
+ let ( m, cat) = match try!( deref_kind ( base_cmt. ty , deref_context ) ) {
904
922
deref_ptr( ptr) => {
905
923
let ptr = if implicit {
906
924
match ptr {
@@ -932,7 +950,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
932
950
933
951
pub fn cat_index < N : ast_node > ( & self ,
934
952
elt : & N ,
935
- mut base_cmt : cmt < ' tcx > )
953
+ mut base_cmt : cmt < ' tcx > ,
954
+ context : InteriorOffsetKind )
936
955
-> McResult < cmt < ' tcx > > {
937
956
//! Creates a cmt for an indexing operation (`[]`).
938
957
//!
@@ -974,18 +993,21 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
974
993
} ;
975
994
976
995
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) ) ;
978
998
979
999
fn interior < ' tcx , N : ast_node > ( elt : & N ,
980
1000
of_cmt : cmt < ' tcx > ,
981
1001
vec_ty : Ty < ' tcx > ,
982
1002
mutbl : MutabilityCategory ,
1003
+ context : InteriorOffsetKind ,
983
1004
element_ty : Ty < ' tcx > ) -> cmt < ' tcx >
984
1005
{
1006
+ let interior_elem = InteriorElement ( context, element_kind ( vec_ty) ) ;
985
1007
Rc :: new ( cmt_ {
986
1008
id : elt. id ( ) ,
987
1009
span : elt. span ( ) ,
988
- cat : cat_interior ( of_cmt, InteriorElement ( element_kind ( vec_ty ) ) ) ,
1010
+ cat : cat_interior ( of_cmt, interior_elem ) ,
989
1011
mutbl : mutbl,
990
1012
ty : element_ty,
991
1013
note : NoteNone
@@ -997,10 +1019,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
997
1019
// underlying vec.
998
1020
fn deref_vec < N : ast_node > ( & self ,
999
1021
elt : & N ,
1000
- base_cmt : cmt < ' tcx > )
1022
+ base_cmt : cmt < ' tcx > ,
1023
+ context : InteriorOffsetKind )
1001
1024
-> McResult < cmt < ' tcx > >
1002
1025
{
1003
- match try!( deref_kind ( base_cmt. ty ) ) {
1026
+ match try!( deref_kind ( base_cmt. ty , Some ( context ) ) ) {
1004
1027
deref_ptr( ptr) => {
1005
1028
// for unique ptrs, we inherit mutability from the
1006
1029
// owning reference.
@@ -1041,7 +1064,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
1041
1064
let ( slice_mutbl, slice_r) = vec_slice_info ( self . tcx ( ) ,
1042
1065
slice_pat,
1043
1066
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) ) ;
1045
1070
return Ok ( ( cmt_slice, slice_mutbl, slice_r) ) ;
1046
1071
1047
1072
/// 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> {
1253
1278
// box p1, &p1, &mut p1. we can ignore the mutability of
1254
1279
// PatRegion since that information is already contained
1255
1280
// in the type.
1256
- let subcmt = try!( self . cat_deref ( pat, cmt, 0 ) ) ;
1281
+ let subcmt = try!( self . cat_deref ( pat, cmt, 0 , None ) ) ;
1257
1282
try!( self . cat_pattern_ ( subcmt, & * * subpat, op) ) ;
1258
1283
}
1259
1284
1260
1285
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) ) ;
1262
1289
for before_pat in before {
1263
1290
try!( self . cat_pattern_ ( elt_cmt. clone ( ) , & * * before_pat, op) ) ;
1264
1291
}
@@ -1455,10 +1482,18 @@ impl<'tcx> cmt_<'tcx> {
1455
1482
cat_interior( _, InteriorField ( PositionalField ( _) ) ) => {
1456
1483
"anonymous field" . to_string ( )
1457
1484
}
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 ) ) => {
1460
1489
"indexed content" . to_string ( )
1461
1490
}
1491
+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1492
+ VecElement ) ) |
1493
+ cat_interior( _, InteriorElement ( InteriorOffsetKind :: Pattern ,
1494
+ OtherElement ) ) => {
1495
+ "pattern-bound indexed content" . to_string ( )
1496
+ }
1462
1497
cat_upvar( ref var) => {
1463
1498
var. user_string ( tcx)
1464
1499
}
@@ -1546,7 +1581,7 @@ impl<'tcx> Repr<'tcx> for InteriorKind {
1546
1581
token:: get_name ( fld) . to_string ( )
1547
1582
}
1548
1583
InteriorField ( PositionalField ( i) ) => format ! ( "#{}" , i) ,
1549
- InteriorElement ( _ ) => "[]" . to_string ( ) ,
1584
+ InteriorElement ( .. ) => "[]" . to_string ( ) ,
1550
1585
}
1551
1586
}
1552
1587
}
0 commit comments