@@ -27,7 +27,7 @@ fn check_crate(tcx: ty::ctxt,
27
27
let bccx = @{ tcx: tcx,
28
28
method_map: method_map,
29
29
msg_level: msg_level,
30
- root_map: int_hash ( ) ,
30
+ root_map: root_map ( ) ,
31
31
mutbl_map: int_hash ( ) } ;
32
32
33
33
let req_loan_map = if msg_level > 0 u {
@@ -53,7 +53,14 @@ type borrowck_ctxt = @{tcx: ty::ctxt,
53
53
// a map mapping id's of expressions of task-local type (@T, []/@, etc) where
54
54
// the box needs to be kept live to the id of the scope for which they must
55
55
// stay live.
56
- type root_map = hashmap < ast:: node_id , ast:: node_id > ;
56
+ type root_map = hashmap < root_map_key , ast:: node_id > ;
57
+
58
+ // the keys to the root map combine the `id` of the expression with
59
+ // the number of types that it is autodereferenced. So, for example,
60
+ // if you have an expression `x.f` and x has type ~@T, we could add an
61
+ // entry {id:x, derefs:0} to refer to `x` itself, `{id:x, derefs:1}`
62
+ // to refer to the deref of the unique pointer, and so on.
63
+ type root_map_key = { id : ast:: node_id , derefs : uint } ;
57
64
58
65
// set of ids of local vars / formal arguments that are modified / moved.
59
66
// this is used in trans for optimization purposes.
@@ -71,13 +78,13 @@ type bckerr = {cmt: cmt, code: bckerr_code};
71
78
type bckres < T > = result < T , bckerr > ;
72
79
73
80
enum categorization {
74
- cat_rvalue, // result of eval'ing some misc expr
75
- cat_special( special_kind ) , //
76
- cat_local( ast:: node_id ) , // local variable
77
- cat_arg( ast:: node_id ) , // formal argument
78
- cat_stack_upvar( cmt ) , // upvar in stack closure
79
- cat_deref( cmt , ptr_kind ) , // deref of a ptr
80
- cat_comp( cmt , comp_kind ) , // adjust to locate an internal component
81
+ cat_rvalue, // result of eval'ing some misc expr
82
+ cat_special( special_kind ) , //
83
+ cat_local( ast:: node_id ) , // local variable
84
+ cat_arg( ast:: node_id ) , // formal argument
85
+ cat_stack_upvar( cmt ) , // upvar in stack closure
86
+ cat_deref( cmt , uint , ptr_kind ) , // deref of a ptr
87
+ cat_comp( cmt , comp_kind ) , // adjust to locate an internal component
81
88
}
82
89
83
90
// different kinds of pointers:
@@ -156,6 +163,18 @@ fn save_and_restore<T:copy,U>(&t: T, f: fn() -> U) -> U {
156
163
ret u;
157
164
}
158
165
166
+ fn root_map ( ) -> root_map {
167
+ ret hashmap ( root_map_key_hash , root_map_key_eq ) ;
168
+
169
+ fn root_map_key_eq ( k1 : root_map_key , k2 : root_map_key ) -> bool {
170
+ k1. id == k2. id && k1. derefs == k2. derefs
171
+ }
172
+
173
+ fn root_map_key_hash ( k : root_map_key ) -> uint {
174
+ ( k. id << 4 ) as uint | k. derefs
175
+ }
176
+ }
177
+
159
178
// ----------------------------------------------------------------------
160
179
// Gathering loans
161
180
//
@@ -374,7 +393,7 @@ impl methods for gather_loan_ctxt {
374
393
375
394
ast:: pat_box( subpat) | ast:: pat_uniq( subpat) {
376
395
// @p1, ~p1
377
- alt self . bccx . cat_deref ( pat, cmt, true ) {
396
+ alt self. bccx. cat_deref( pat, cmt, 0 u , true ) {
378
397
some( subcmt) { self . gather_pat( subcmt, subpat, alt_id) ; }
379
398
none { tcx. sess. span_bug( pat. span, "Non derefable type" ) ; }
380
399
}
@@ -915,7 +934,7 @@ impl categorize_methods for borrowck_ctxt {
915
934
916
935
ty:: ty_uniq( * ) | ty:: ty_box( * ) | ty:: ty_rptr( * ) {
917
936
let cmt = self . cat_expr( expr) ;
918
- self . cat_deref ( expr, cmt, true ) . get ( )
937
+ self . cat_deref( expr, cmt, 0 u , true ) . get( )
919
938
}
920
939
921
940
_ {
@@ -943,7 +962,7 @@ impl categorize_methods for borrowck_ctxt {
943
962
alt expr. node {
944
963
ast:: expr_unary( ast:: deref, e_base) {
945
964
let base_cmt = self . cat_expr( e_base) ;
946
- alt self. cat_deref ( expr, base_cmt, true ) {
965
+ alt self . cat_deref( expr, base_cmt, 0 u , true) {
947
966
some( cmt) { ret cmt; }
948
967
none {
949
968
tcx. sess. span_bug(
@@ -955,7 +974,7 @@ impl categorize_methods for borrowck_ctxt {
955
974
}
956
975
957
976
ast:: expr_field( base, f_name, _) {
958
- let base_cmt = self . cat_autoderef ( expr , base) ;
977
+ let base_cmt = self . cat_autoderef( base) ;
959
978
self . cat_field( expr, base_cmt, f_name, expr_ty)
960
979
}
961
980
@@ -1010,7 +1029,7 @@ impl categorize_methods for borrowck_ctxt {
1010
1029
mutbl: m, ty: f_ty}
1011
1030
}
1012
1031
1013
- fn cat_deref < N : ast_node > ( node : N , base_cmt : cmt ,
1032
+ fn cat_deref < N : ast_node > ( node: N , base_cmt: cmt, derefs : uint ,
1014
1033
expl: bool) -> option < cmt > {
1015
1034
ty:: deref ( self . tcx, base_cmt. ty, expl) . map { |mt|
1016
1035
alt deref_kind( self . tcx, base_cmt. ty) {
@@ -1027,7 +1046,7 @@ impl categorize_methods for borrowck_ctxt {
1027
1046
}
1028
1047
} ;
1029
1048
@{ id: node. id( ) , span: node. span( ) ,
1030
- cat: cat_deref ( base_cmt, ptr) , lp: lp,
1049
+ cat: cat_deref( base_cmt, derefs , ptr) , lp: lp,
1031
1050
mutbl: mt. mutbl, ty: mt. ty}
1032
1051
}
1033
1052
@@ -1041,7 +1060,7 @@ impl categorize_methods for borrowck_ctxt {
1041
1060
}
1042
1061
}
1043
1062
1044
- fn cat_autoderef ( expr : @ast :: expr , base : @ast:: expr ) -> cmt {
1063
+ fn cat_autoderef( base: @ast:: expr) -> cmt {
1045
1064
// Creates a string of implicit derefences so long as base is
1046
1065
// dereferencable. n.b., it is important that these dereferences are
1047
1066
// associated with the field/index that caused the autoderef (expr).
@@ -1050,16 +1069,18 @@ impl categorize_methods for borrowck_ctxt {
1050
1069
// Given something like base.f where base has type @m1 @m2 T, we want
1051
1070
// to yield the equivalent categories to (**base).f.
1052
1071
let mut cmt = self . cat_expr( base) ;
1072
+ let mut ctr = 0 u;
1053
1073
loop {
1054
- alt self . cat_deref ( expr, cmt, false ) {
1074
+ ctr += 1 u;
1075
+ alt self. cat_deref( base, cmt, ctr, false) {
1055
1076
none { ret cmt; }
1056
1077
some( cmt1) { cmt = cmt1; }
1057
1078
}
1058
1079
}
1059
1080
}
1060
1081
1061
1082
fn cat_index( expr: @ast:: expr, base: @ast:: expr) -> cmt {
1062
- let base_cmt = self . cat_autoderef ( expr , base) ;
1083
+ let base_cmt = self . cat_autoderef( base) ;
1063
1084
1064
1085
let mt = alt ty:: index( self . tcx, base_cmt. ty) {
1065
1086
some( mt) { mt }
@@ -1084,7 +1105,7 @@ impl categorize_methods for borrowck_ctxt {
1084
1105
// the head of this section
1085
1106
let deref_lp = base_cmt. lp. map { |lp| @lp_deref( lp, ptr) } ;
1086
1107
let deref_cmt = @{ id: expr. id, span: expr. span,
1087
- cat: cat_deref ( base_cmt, ptr) , lp: deref_lp,
1108
+ cat: cat_deref( base_cmt, 0 u , ptr) , lp: deref_lp,
1088
1109
mutbl: mt. mutbl, ty: mt. ty} ;
1089
1110
let comp = comp_index( base_cmt. ty) ;
1090
1111
let index_lp = deref_lp. map { |lp| @lp_comp( lp, comp) } ;
@@ -1211,8 +1232,9 @@ impl categorize_methods for borrowck_ctxt {
1211
1232
cat_rvalue { "rvalue" }
1212
1233
cat_local( node_id) { #fmt[ "local(%d)" , node_id] }
1213
1234
cat_arg( node_id) { #fmt[ "arg(%d)" , node_id] }
1214
- cat_deref ( cmt, ptr) {
1215
- #fmt[ "%s->(%s)" , self . cat_to_repr ( cmt. cat ) , self . ptr_sigil ( ptr) ]
1235
+ cat_deref( cmt, derefs, ptr) {
1236
+ #fmt[ "%s->(%s, %u)" , self . cat_to_repr( cmt. cat) ,
1237
+ self . ptr_sigil( ptr) , derefs]
1216
1238
}
1217
1239
cat_comp( cmt, comp) {
1218
1240
#fmt[ "%s.%s" , self . cat_to_repr( cmt. cat) , self . comp_to_repr( comp) ]
@@ -1285,7 +1307,7 @@ impl categorize_methods for borrowck_ctxt {
1285
1307
cat_rvalue { "non-lvalue" }
1286
1308
cat_local( _) { mut_str + " local variable" }
1287
1309
cat_arg( _) { mut_str + " argument" }
1288
- cat_deref ( _ , _ ) { "dereference of " + mut_str + " pointer" }
1310
+ cat_deref( * ) { "dereference of " + mut_str + " pointer" }
1289
1311
cat_stack_upvar( _) { mut_str + " upvar" }
1290
1312
cat_comp( _, comp_field( _) ) { mut_str + " field" }
1291
1313
cat_comp( _, comp_tuple) { "tuple content" }
@@ -1446,26 +1468,31 @@ impl preserve_methods for preserve_ctxt {
1446
1468
cat_comp( cmt1, comp_variant) {
1447
1469
self . require_imm( cmt, cmt1, err_mut_variant)
1448
1470
}
1449
- cat_deref( cmt1, uniq_ptr) {
1471
+ cat_deref( cmt1, _ , uniq_ptr) {
1450
1472
self . require_imm( cmt, cmt1, err_mut_uniq)
1451
1473
}
1452
- cat_deref( _, region_ptr) {
1474
+ cat_deref( _, _ , region_ptr) {
1453
1475
// References are always "stable" by induction (when the
1454
1476
// reference of type &MT was created, the memory must have
1455
1477
// been stable)
1456
1478
ok( ( ) )
1457
1479
}
1458
- cat_deref( _, unsafe_ptr) {
1480
+ cat_deref( _, _ , unsafe_ptr) {
1459
1481
// Unsafe pointers are the user's problem
1460
1482
ok( ( ) )
1461
1483
}
1462
- cat_deref( _, gc_ptr) {
1484
+ cat_deref( _, derefs , gc_ptr) {
1463
1485
// GC'd pointers of type @MT: always stable because we can inc
1464
1486
// the ref count or keep a GC root as necessary. We need to
1465
1487
// insert this id into the root_map, however.
1466
1488
alt self. opt_scope_id {
1467
1489
some( scope_id) {
1468
- self . bccx. root_map. insert( cmt. id, scope_id) ;
1490
+ #debug[ "Inserting root map entry for %s: \
1491
+ node %d:%u -> scope %d",
1492
+ self . bccx. cmt_to_repr( cmt) , cmt. id,
1493
+ derefs, scope_id] ;
1494
+ let rk = { id: cmt. id, derefs: derefs} ;
1495
+ self . bccx. root_map. insert( rk, scope_id) ;
1469
1496
ok( ( ) )
1470
1497
}
1471
1498
none {
@@ -1562,7 +1589,7 @@ impl loan_methods for loan_ctxt {
1562
1589
}
1563
1590
}
1564
1591
cat_comp( cmt1, comp_variant) |
1565
- cat_deref( cmt1, uniq_ptr) {
1592
+ cat_deref( cmt1, _ , uniq_ptr) {
1566
1593
// Variant components: the base must be immutable, because
1567
1594
// if it is overwritten, the types of the embedded data
1568
1595
// could change.
@@ -1573,9 +1600,9 @@ impl loan_methods for loan_ctxt {
1573
1600
self . ok_with_loan_of( cmt, req_mutbl)
1574
1601
}
1575
1602
}
1576
- cat_deref( cmt1, unsafe_ptr) |
1577
- cat_deref( cmt1, gc_ptr) |
1578
- cat_deref( cmt1, region_ptr) {
1603
+ cat_deref( cmt1, _ , unsafe_ptr) |
1604
+ cat_deref( cmt1, _ , gc_ptr) |
1605
+ cat_deref( cmt1, _ , region_ptr) {
1579
1606
// Aliased data is simply not lendable.
1580
1607
self . bccx. tcx. sess. span_bug(
1581
1608
cmt. span,
0 commit comments