@@ -260,104 +260,133 @@ impl ReachableContext {
260260 continue
261261 }
262262 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.
268263 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, _) => {
270287 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) ;
275290 }
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+ }
276303
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, ( ) )
291310 }
311+ }
292312
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 ) ;
297325 }
298326 }
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+ }
299335
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 ) ;
309344 }
310345 }
311346 }
347+ }
312348
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( * ) => { }
318354
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?!")
324359 }
325360 }
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
334366 }
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 , ( ) )
339369 }
340370 }
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 , ( ) )
359375 }
360376 }
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+ }
361390 }
362391 }
363392
0 commit comments