@@ -16,12 +16,18 @@ impl public_methods for borrowck_ctxt {
16
16
self . preserve ( cmt, opt_scope_id)
17
17
}
18
18
cat_local ( _) {
19
- // This should never happen. Local variables are always lendable,
20
- // so either `loan()` should be called or there must be some
21
- // intermediate @ or &---they are not lendable but do not recurse.
22
- self . tcx . sess . span_bug (
23
- cmt. span ,
24
- "preserve() called with local" ) ;
19
+ // Normally, local variables are lendable, and so this
20
+ // case should never trigged. However, if we are
21
+ // preserving an expression like a.b where the field `b`
22
+ // has @ type, then it will recurse to ensure that the `a`
23
+ // is stable to try and avoid rooting the value `a.b`. In
24
+ // this case, opt_scope_id will be none.
25
+ if opt_scope_id. is_some ( ) {
26
+ self . tcx . sess . span_bug (
27
+ cmt. span ,
28
+ "preserve() called with local and non-none opt_scope_id" ) ;
29
+ }
30
+ ok ( ( ) )
25
31
}
26
32
cat_arg ( _) {
27
33
// This can happen as not all args are lendable (e.g., &&
@@ -37,11 +43,11 @@ impl public_methods for borrowck_ctxt {
37
43
// type never changes.
38
44
self . preserve ( cmt_base, opt_scope_id)
39
45
}
40
- cat_comp ( cmt1 , comp_variant) {
41
- self . require_imm ( cmt, cmt1 , opt_scope_id, err_mut_variant)
46
+ cat_comp ( cmt_base , comp_variant) {
47
+ self . require_imm ( cmt, cmt_base , opt_scope_id, err_mut_variant)
42
48
}
43
- cat_deref ( cmt1 , _, uniq_ptr) {
44
- self . require_imm ( cmt, cmt1 , opt_scope_id, err_mut_uniq)
49
+ cat_deref ( cmt_base , _, uniq_ptr) {
50
+ self . require_imm ( cmt, cmt_base , opt_scope_id, err_mut_uniq)
45
51
}
46
52
cat_deref ( _, _, region_ptr) {
47
53
// References are always "stable" by induction (when the
@@ -54,23 +60,18 @@ impl public_methods for borrowck_ctxt {
54
60
ok ( ( ) )
55
61
}
56
62
cat_deref ( base, derefs, gc_ptr) {
57
- // GC'd pointers of type @MT: always stable because we can
58
- // inc the ref count or keep a GC root as necessary. We
59
- // need to insert this id into the root_map, however.
60
- alt opt_scope_id {
61
- some( scope_id) {
62
- #debug[ "Inserting root map entry for %s: \
63
- node %d:%u -> scope %d",
64
- self . cmt_to_repr ( cmt) , base. id ,
65
- derefs, scope_id] ;
66
-
67
- let rk = { id: base. id , derefs: derefs} ;
68
- self . root_map . insert ( rk, scope_id) ;
69
- ok ( ( ) )
70
- }
71
- none {
72
- err( { cmt: cmt, code: err_preserve_gc} )
73
- }
63
+ // GC'd pointers of type @MT: if this pointer lives in
64
+ // immutable, stable memory, then everything is fine. But
65
+ // otherwise we have no guarantee the pointer will stay
66
+ // live, so we must root the pointer (i.e., inc the ref
67
+ // count) for the duration of the loan.
68
+ if base. mutbl == m_imm {
69
+ alt self . preserve ( base, none) {
70
+ ok ( ( ) ) { ok ( ( ) ) }
71
+ err ( _) { self . attempt_root ( cmt, opt_scope_id, base, derefs) }
72
+ }
73
+ } else {
74
+ self . attempt_root ( cmt, opt_scope_id, base, derefs)
74
75
}
75
76
}
76
77
cat_discr ( base, alt_id) {
@@ -138,14 +139,33 @@ impl public_methods for borrowck_ctxt {
138
139
139
140
impl private_methods for borrowck_ctxt {
140
141
fn require_imm ( cmt : cmt ,
141
- cmt1 : cmt ,
142
+ cmt_base : cmt ,
142
143
opt_scope_id : option < ast:: node_id > ,
143
144
code : bckerr_code ) -> bckres < ( ) > {
144
145
// Variant contents and unique pointers: must be immutably
145
146
// rooted to a preserved address.
146
- alt cmt1 . mutbl {
147
+ alt cmt_base . mutbl {
147
148
m_mutbl | m_const { err( { cmt : cmt, code : code} ) }
148
- m_imm { self. preserve ( cmt1, opt_scope_id) }
149
+ m_imm { self. preserve ( cmt_base, opt_scope_id) }
150
+ }
151
+ }
152
+
153
+ fn attempt_root ( cmt : cmt , opt_scope_id : option < ast:: node_id > ,
154
+ base : cmt , derefs : uint ) -> bckres < ( ) > {
155
+ alt opt_scope_id {
156
+ some( scope_id) {
157
+ #debug[ "Inserting root map entry for %s: \
158
+ node %d:%u -> scope %d",
159
+ self . cmt_to_repr ( cmt) , base. id ,
160
+ derefs, scope_id] ;
161
+
162
+ let rk = { id: base. id , derefs: derefs} ;
163
+ self . root_map . insert ( rk, scope_id) ;
164
+ ok ( ( ) )
165
+ }
166
+ none {
167
+ err( { cmt: cmt, code: err_preserve_gc} )
168
+ }
149
169
}
150
170
}
151
171
}
0 commit comments