@@ -20,7 +20,6 @@ use middle::typeck;
20
20
use middle:: privacy;
21
21
use util:: nodemap:: NodeSet ;
22
22
23
- use std:: cell:: RefCell ;
24
23
use std:: vec_ng:: Vec ;
25
24
use collections:: HashSet ;
26
25
use syntax:: ast;
@@ -90,27 +89,19 @@ struct ReachableContext<'a> {
90
89
// methods they've been resolved to.
91
90
method_map : typeck:: MethodMap ,
92
91
// The set of items which must be exported in the linkage sense.
93
- reachable_symbols : @ RefCell < NodeSet > ,
92
+ reachable_symbols : NodeSet ,
94
93
// A worklist of item IDs. Each item ID in this worklist will be inlined
95
94
// and will be scanned for further references.
96
- worklist : @ RefCell < Vec < ast:: NodeId > > ,
95
+ worklist : Vec < ast:: NodeId > ,
97
96
}
98
97
99
- struct MarkSymbolVisitor < ' a > {
100
- worklist : @RefCell < Vec < ast:: NodeId > > ,
101
- method_map : typeck:: MethodMap ,
102
- tcx : & ' a ty:: ctxt ,
103
- reachable_symbols : @RefCell < NodeSet > ,
104
- }
105
-
106
- impl < ' a > Visitor < ( ) > for MarkSymbolVisitor < ' a > {
98
+ impl < ' a > Visitor < ( ) > for ReachableContext < ' a > {
107
99
108
100
fn visit_expr ( & mut self , expr : & ast:: Expr , _: ( ) ) {
109
101
110
102
match expr. node {
111
103
ast:: ExprPath ( _) => {
112
- let def_map = self . tcx . def_map . borrow ( ) ;
113
- let def = match def_map. get ( ) . find ( & expr. id ) {
104
+ let def = match self . tcx . def_map . borrow ( ) . get ( ) . find ( & expr. id ) {
114
105
Some ( & def) => def,
115
106
None => {
116
107
self . tcx . sess . span_bug ( expr. span ,
@@ -120,29 +111,22 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
120
111
121
112
let def_id = def_id_of_def ( def) ;
122
113
if is_local ( def_id) {
123
- if ReachableContext ::
124
- def_id_represents_local_inlined_item ( self . tcx , def_id) {
125
- {
126
- let mut worklist = self . worklist . borrow_mut ( ) ;
127
- worklist. get ( ) . push ( def_id. node )
128
- }
114
+ if self . def_id_represents_local_inlined_item ( def_id) {
115
+ self . worklist . push ( def_id. node )
129
116
} else {
130
117
match def {
131
118
// If this path leads to a static, then we may have
132
119
// to do some work to figure out whether the static
133
120
// is indeed reachable (address_insignificant
134
121
// statics are *never* reachable).
135
122
ast:: DefStatic ( ..) => {
136
- let mut worklist = self . worklist . borrow_mut ( ) ;
137
- worklist. get ( ) . push ( def_id. node ) ;
123
+ self . worklist . push ( def_id. node ) ;
138
124
}
139
125
140
126
// If this wasn't a static, then this destination is
141
127
// surely reachable.
142
128
_ => {
143
- let mut reachable_symbols =
144
- self . reachable_symbols . borrow_mut ( ) ;
145
- reachable_symbols. get ( ) . insert ( def_id. node ) ;
129
+ self . reachable_symbols . insert ( def_id. node ) ;
146
130
}
147
131
}
148
132
}
@@ -153,13 +137,10 @@ impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
153
137
match self . method_map . borrow ( ) . get ( ) . get ( & method_call) . origin {
154
138
typeck:: MethodStatic ( def_id) => {
155
139
if is_local ( def_id) {
156
- if ReachableContext ::
157
- def_id_represents_local_inlined_item (
158
- self . tcx ,
159
- def_id) {
160
- self . worklist . borrow_mut ( ) . get ( ) . push ( def_id. node )
140
+ if self . def_id_represents_local_inlined_item ( def_id) {
141
+ self . worklist . push ( def_id. node )
161
142
}
162
- self . reachable_symbols . borrow_mut ( ) . get ( ) . insert ( def_id. node ) ;
143
+ self . reachable_symbols . insert ( def_id. node ) ;
163
144
}
164
145
}
165
146
_ => { }
@@ -183,21 +164,20 @@ impl<'a> ReachableContext<'a> {
183
164
ReachableContext {
184
165
tcx : tcx,
185
166
method_map : method_map,
186
- reachable_symbols : @ RefCell :: new ( NodeSet :: new ( ) ) ,
187
- worklist : @ RefCell :: new ( Vec :: new ( ) ) ,
167
+ reachable_symbols : NodeSet :: new ( ) ,
168
+ worklist : Vec :: new ( ) ,
188
169
}
189
170
}
190
171
191
172
// Returns true if the given def ID represents a local item that is
192
173
// eligible for inlining and false otherwise.
193
- fn def_id_represents_local_inlined_item ( tcx : & ty:: ctxt , def_id : ast:: DefId )
194
- -> bool {
174
+ fn def_id_represents_local_inlined_item ( & self , def_id : ast:: DefId ) -> bool {
195
175
if def_id. krate != ast:: LOCAL_CRATE {
196
176
return false
197
177
}
198
178
199
179
let node_id = def_id. node ;
200
- match tcx. map . find ( node_id) {
180
+ match self . tcx . map . find ( node_id) {
201
181
Some ( ast_map:: NodeItem ( item) ) => {
202
182
match item. node {
203
183
ast:: ItemFn ( ..) => item_might_be_inlined ( item) ,
@@ -215,11 +195,11 @@ impl<'a> ReachableContext<'a> {
215
195
attributes_specify_inlining ( method. attrs . as_slice ( ) ) {
216
196
true
217
197
} else {
218
- let impl_did = tcx. map . get_parent_did ( node_id) ;
198
+ let impl_did = self . tcx . map . get_parent_did ( node_id) ;
219
199
// Check the impl. If the generics on the self type of the
220
200
// impl require inlining, this method does too.
221
201
assert ! ( impl_did. krate == ast:: LOCAL_CRATE ) ;
222
- match tcx. map . expect_item ( impl_did. node ) . node {
202
+ match self . tcx . map . expect_item ( impl_did. node ) . node {
223
203
ast:: ItemImpl ( ref generics, _, _, _) => {
224
204
generics_require_inlining ( generics)
225
205
}
@@ -232,40 +212,21 @@ impl<'a> ReachableContext<'a> {
232
212
}
233
213
}
234
214
235
- // Helper function to set up a visitor for `propagate()` below.
236
- fn init_visitor ( & self ) -> MarkSymbolVisitor < ' a > {
237
- let ( worklist, method_map) = ( self . worklist , self . method_map ) ;
238
- let ( tcx, reachable_symbols) = ( self . tcx , self . reachable_symbols ) ;
239
-
240
- MarkSymbolVisitor {
241
- worklist : worklist,
242
- method_map : method_map,
243
- tcx : tcx,
244
- reachable_symbols : reachable_symbols,
245
- }
246
- }
247
-
248
215
// Step 2: Mark all symbols that the symbols on the worklist touch.
249
- fn propagate ( & self ) {
250
- let mut visitor = self . init_visitor ( ) ;
216
+ fn propagate ( & mut self ) {
251
217
let mut scanned = HashSet :: new ( ) ;
252
218
loop {
253
- let search_item = {
254
- let mut worklist = self . worklist . borrow_mut ( ) ;
255
- if worklist. get ( ) . len ( ) == 0 {
256
- break
257
- }
258
- let search_item = worklist. get ( ) . pop ( ) . unwrap ( ) ;
259
- if scanned. contains ( & search_item) {
260
- continue
261
- }
262
- search_item
263
- } ;
219
+ if self . worklist . len ( ) == 0 {
220
+ break
221
+ }
222
+ let search_item = self . worklist . pop ( ) . unwrap ( ) ;
223
+ if scanned. contains ( & search_item) {
224
+ continue
225
+ }
264
226
265
227
scanned. insert ( search_item) ;
266
228
match self . tcx . map . find ( search_item) {
267
- Some ( ref item) => self . propagate_node ( item, search_item,
268
- & mut visitor) ,
229
+ Some ( ref item) => self . propagate_node ( item, search_item) ,
269
230
None if search_item == ast:: CRATE_NODE_ID => { }
270
231
None => {
271
232
self . tcx . sess . bug ( format ! ( "found unmapped ID in worklist: \
@@ -276,9 +237,8 @@ impl<'a> ReachableContext<'a> {
276
237
}
277
238
}
278
239
279
- fn propagate_node ( & self , node : & ast_map:: Node ,
280
- search_item : ast:: NodeId ,
281
- visitor : & mut MarkSymbolVisitor ) {
240
+ fn propagate_node ( & mut self , node : & ast_map:: Node ,
241
+ search_item : ast:: NodeId ) {
282
242
if !self . tcx . sess . building_library . get ( ) {
283
243
// If we are building an executable, then there's no need to flag
284
244
// anything as external except for `extern fn` types. These
@@ -289,9 +249,7 @@ impl<'a> ReachableContext<'a> {
289
249
ast_map:: NodeItem ( item) => {
290
250
match item. node {
291
251
ast:: ItemFn ( _, ast:: ExternFn , _, _, _) => {
292
- let mut reachable_symbols =
293
- self . reachable_symbols . borrow_mut ( ) ;
294
- reachable_symbols. get ( ) . insert ( search_item) ;
252
+ self . reachable_symbols . insert ( search_item) ;
295
253
}
296
254
_ => { }
297
255
}
@@ -303,16 +261,15 @@ impl<'a> ReachableContext<'a> {
303
261
// continue to participate in linkage after this product is
304
262
// produced. In this case, we traverse the ast node, recursing on
305
263
// all reachable nodes from this one.
306
- let mut reachable_symbols = self . reachable_symbols . borrow_mut ( ) ;
307
- reachable_symbols. get ( ) . insert ( search_item) ;
264
+ self . reachable_symbols . insert ( search_item) ;
308
265
}
309
266
310
267
match * node {
311
268
ast_map:: NodeItem ( item) => {
312
269
match item. node {
313
270
ast:: ItemFn ( _, _, _, _, search_block) => {
314
271
if item_might_be_inlined ( item) {
315
- visit:: walk_block ( visitor , search_block, ( ) )
272
+ visit:: walk_block ( self , search_block, ( ) )
316
273
}
317
274
}
318
275
@@ -321,9 +278,7 @@ impl<'a> ReachableContext<'a> {
321
278
ast:: ItemStatic ( ..) => {
322
279
if attr:: contains_name ( item. attrs . as_slice ( ) ,
323
280
"address_insignificant" ) {
324
- let mut reachable_symbols =
325
- self . reachable_symbols . borrow_mut ( ) ;
326
- reachable_symbols. get ( ) . remove ( & search_item) ;
281
+ self . reachable_symbols . remove ( & search_item) ;
327
282
}
328
283
}
329
284
@@ -348,14 +303,14 @@ impl<'a> ReachableContext<'a> {
348
303
// Keep going, nothing to get exported
349
304
}
350
305
ast:: Provided ( ref method) => {
351
- visit:: walk_block ( visitor , method. body , ( ) )
306
+ visit:: walk_block ( self , method. body , ( ) )
352
307
}
353
308
}
354
309
}
355
310
ast_map:: NodeMethod ( method) => {
356
311
let did = self . tcx . map . get_parent_did ( search_item) ;
357
312
if method_might_be_inlined ( self . tcx , method, did) {
358
- visit:: walk_block ( visitor , method. body , ( ) )
313
+ visit:: walk_block ( self , method. body , ( ) )
359
314
}
360
315
}
361
316
// Nothing to recurse on for these
@@ -375,13 +330,10 @@ impl<'a> ReachableContext<'a> {
375
330
// FIXME(pcwalton): This is a conservative overapproximation, but fixing
376
331
// this properly would result in the necessity of computing *type*
377
332
// reachability, which might result in a compile time loss.
378
- fn mark_destructors_reachable ( & self ) {
379
- let destructor_for_type = self . tcx . destructor_for_type . borrow ( ) ;
380
- for ( _, destructor_def_id) in destructor_for_type. get ( ) . iter ( ) {
333
+ fn mark_destructors_reachable ( & mut self ) {
334
+ for ( _, destructor_def_id) in self . tcx . destructor_for_type . borrow ( ) . get ( ) . iter ( ) {
381
335
if destructor_def_id. krate == ast:: LOCAL_CRATE {
382
- let mut reachable_symbols = self . reachable_symbols
383
- . borrow_mut ( ) ;
384
- reachable_symbols. get ( ) . insert ( destructor_def_id. node ) ;
336
+ self . reachable_symbols . insert ( destructor_def_id. node ) ;
385
337
}
386
338
}
387
339
}
@@ -390,27 +342,25 @@ impl<'a> ReachableContext<'a> {
390
342
pub fn find_reachable ( tcx : & ty:: ctxt ,
391
343
method_map : typeck:: MethodMap ,
392
344
exported_items : & privacy:: ExportedItems )
393
- -> @ RefCell < NodeSet > {
394
- let reachable_context = ReachableContext :: new ( tcx, method_map) ;
345
+ -> NodeSet {
346
+ let mut reachable_context = ReachableContext :: new ( tcx, method_map) ;
395
347
396
348
// Step 1: Seed the worklist with all nodes which were found to be public as
397
349
// a result of the privacy pass along with all local lang items. If
398
350
// other crates link to us, they're going to expect to be able to
399
351
// use the lang items, so we need to be sure to mark them as
400
352
// exported.
401
- let mut worklist = reachable_context. worklist . borrow_mut ( ) ;
402
353
for & id in exported_items. iter ( ) {
403
- worklist . get ( ) . push ( id) ;
354
+ reachable_context . worklist . push ( id) ;
404
355
}
405
356
for ( _, item) in tcx. lang_items . items ( ) {
406
357
match * item {
407
358
Some ( did) if is_local ( did) => {
408
- worklist . get ( ) . push ( did. node ) ;
359
+ reachable_context . worklist . push ( did. node ) ;
409
360
}
410
361
_ => { }
411
362
}
412
363
}
413
- drop ( worklist) ;
414
364
415
365
// Step 2: Mark all symbols that the symbols on the worklist touch.
416
366
reachable_context. propagate ( ) ;
0 commit comments