@@ -260,104 +260,133 @@ impl ReachableContext {
260
260
continue
261
261
}
262
262
scanned. insert ( search_item) ;
263
- self . reachable_symbols . insert ( search_item) ;
264
-
265
- // Find the AST block corresponding to the item and visit it,
266
- // marking all path expressions that resolve to something
267
- // interesting.
268
263
match self . tcx . items . find ( & search_item) {
269
- Some ( & ast_map:: node_item( item, _) ) => {
264
+ Some ( item) => self . propagate_node ( item, search_item,
265
+ & mut visitor) ,
266
+ None if search_item == ast:: CRATE_NODE_ID => { }
267
+ None => {
268
+ self . tcx . sess . bug ( format ! ( "found unmapped ID in worklist: \
269
+ {}",
270
+ search_item) )
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ fn propagate_node ( & self , node : & ast_map:: ast_node ,
277
+ search_item : ast:: NodeId ,
278
+ visitor : & mut MarkSymbolVisitor ) {
279
+ if !* self . tcx . sess . building_library {
280
+ // If we are building an executable, then there's no need to flag
281
+ // anything as external except for `extern fn` types. These
282
+ // functions may still participate in some form of native interface,
283
+ // but all other rust-only interfaces can be private (they will not
284
+ // participate in linkage after this product is produced)
285
+ match * node {
286
+ ast_map:: node_item( item, _) => {
270
287
match item. node {
271
- ast:: item_fn( _, _, _, _, ref search_block) => {
272
- if item_might_be_inlined ( item) {
273
- visit:: walk_block ( & mut visitor, search_block, ( ) )
274
- }
288
+ ast:: item_fn( _, ast:: extern_fn, _, _, _) => {
289
+ self . reachable_symbols . insert ( search_item) ;
275
290
}
291
+ _ => { }
292
+ }
293
+ }
294
+ _ => { }
295
+ }
296
+ } else {
297
+ // If we are building a library, then reachable symbols will
298
+ // continue to participate in linkage after this product is
299
+ // produced. In this case, we traverse the ast node, recursing on
300
+ // all reachable nodes from this one.
301
+ self . reachable_symbols . insert ( search_item) ;
302
+ }
276
303
277
- // Implementations of exported structs/enums need to get
278
- // added to the worklist (as all their methods should be
279
- // accessible)
280
- ast:: item_struct( * ) | ast:: item_enum( * ) => {
281
- let def = local_def ( item. id ) ;
282
- let impls = match self . tcx . inherent_impls . find ( & def) {
283
- Some ( & impls) => impls,
284
- None => continue
285
- } ;
286
- for imp in impls. iter ( ) {
287
- if is_local ( imp. did ) {
288
- self . worklist . push ( imp. did . node ) ;
289
- }
290
- }
304
+ match * node {
305
+ ast_map:: node_item( item, _) => {
306
+ match item. node {
307
+ ast:: item_fn( _, _, _, _, ref search_block) => {
308
+ if item_might_be_inlined ( item) {
309
+ visit:: walk_block ( visitor, search_block, ( ) )
291
310
}
311
+ }
292
312
293
- // Propagate through this impl
294
- ast:: item_impl( _, _, _, ref methods) => {
295
- for method in methods. iter ( ) {
296
- self . worklist . push ( method. id ) ;
313
+ // Implementations of exported structs/enums need to get
314
+ // added to the worklist (as all their methods should be
315
+ // accessible)
316
+ ast:: item_struct( * ) | ast:: item_enum( * ) => {
317
+ let def = local_def ( item. id ) ;
318
+ let impls = match self . tcx . inherent_impls . find ( & def) {
319
+ Some ( & impls) => impls,
320
+ None => return
321
+ } ;
322
+ for imp in impls. iter ( ) {
323
+ if is_local ( imp. did ) {
324
+ self . worklist . push ( imp. did . node ) ;
297
325
}
298
326
}
327
+ }
328
+
329
+ // Propagate through this impl
330
+ ast:: item_impl( _, _, _, ref methods) => {
331
+ for method in methods. iter ( ) {
332
+ self . worklist . push ( method. id ) ;
333
+ }
334
+ }
299
335
300
- // Default methods of exported traits need to all be
301
- // accessible.
302
- ast:: item_trait( _, _, ref methods) => {
303
- for method in methods. iter ( ) {
304
- match * method {
305
- ast:: required( * ) => { }
306
- ast:: provided( ref method) => {
307
- self . worklist . push ( method. id ) ;
308
- }
336
+ // Default methods of exported traits need to all be
337
+ // accessible.
338
+ ast:: item_trait( _, _, ref methods) => {
339
+ for method in methods. iter ( ) {
340
+ match * method {
341
+ ast:: required( * ) => { }
342
+ ast:: provided( ref method) => {
343
+ self . worklist . push ( method. id ) ;
309
344
}
310
345
}
311
346
}
347
+ }
312
348
313
- // These are normal, nothing reachable about these
314
- // inherently and their children are already in the
315
- // worklist
316
- ast:: item_static( * ) | ast:: item_ty( * ) |
317
- ast:: item_mod( * ) | ast:: item_foreign_mod( * ) => { }
349
+ // These are normal, nothing reachable about these
350
+ // inherently and their children are already in the
351
+ // worklist
352
+ ast:: item_static( * ) | ast:: item_ty( * ) |
353
+ ast:: item_mod( * ) | ast:: item_foreign_mod( * ) => { }
318
354
319
- _ => {
320
- self . tcx . sess . span_bug ( item. span ,
321
- "found non-function item \
322
- in worklist?!")
323
- }
355
+ _ => {
356
+ self . tcx . sess . span_bug ( item. span ,
357
+ "found non-function item \
358
+ in worklist?!")
324
359
}
325
360
}
326
- Some ( & ast_map:: node_trait_method( trait_method, _, _) ) => {
327
- match * trait_method {
328
- ast:: required( * ) => {
329
- // Keep going, nothing to get exported
330
- }
331
- ast:: provided( ref method) => {
332
- visit:: walk_block ( & mut visitor, & method. body , ( ) )
333
- }
361
+ }
362
+ ast_map:: node_trait_method( trait_method, _, _) => {
363
+ match * trait_method {
364
+ ast:: required( * ) => {
365
+ // Keep going, nothing to get exported
334
366
}
335
- }
336
- Some ( & ast_map:: node_method( method, did, _) ) => {
337
- if method_might_be_inlined ( self . tcx , method, did) {
338
- visit:: walk_block ( & mut visitor, & method. body , ( ) )
367
+ ast:: provided( ref method) => {
368
+ visit:: walk_block ( visitor, & method. body , ( ) )
339
369
}
340
370
}
341
- // Nothing to recurse on for these
342
- Some ( & ast_map:: node_foreign_item( * ) ) |
343
- Some ( & ast_map:: node_variant( * ) ) |
344
- Some ( & ast_map:: node_struct_ctor( * ) ) => { }
345
- Some ( _) => {
346
- let ident_interner = token:: get_ident_interner ( ) ;
347
- let desc = ast_map:: node_id_to_str ( self . tcx . items ,
348
- search_item,
349
- ident_interner) ;
350
- self . tcx . sess . bug ( format ! ( "found unexpected thingy in \
351
- worklist: {}",
352
- desc) )
353
- }
354
- None if search_item == ast:: CRATE_NODE_ID => { }
355
- None => {
356
- self . tcx . sess . bug ( format ! ( "found unmapped ID in worklist: \
357
- {}",
358
- search_item) )
371
+ }
372
+ ast_map:: node_method( method, did, _) => {
373
+ if method_might_be_inlined ( self . tcx , method, did) {
374
+ visit:: walk_block ( visitor, & method. body , ( ) )
359
375
}
360
376
}
377
+ // Nothing to recurse on for these
378
+ ast_map:: node_foreign_item( * ) |
379
+ ast_map:: node_variant( * ) |
380
+ ast_map:: node_struct_ctor( * ) => { }
381
+ _ => {
382
+ let ident_interner = token:: get_ident_interner ( ) ;
383
+ let desc = ast_map:: node_id_to_str ( self . tcx . items ,
384
+ search_item,
385
+ ident_interner) ;
386
+ self . tcx . sess . bug ( format ! ( "found unexpected thingy in \
387
+ worklist: {}",
388
+ desc) )
389
+ }
361
390
}
362
391
}
363
392
0 commit comments