@@ -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