@@ -21,36 +21,36 @@ use middle::privacy;
2121use middle:: resolve;
2222
2323use std:: hashmap:: HashSet ;
24- use syntax:: ast:: * ;
24+ use syntax:: ast;
2525use syntax:: ast_map;
26- use syntax:: ast_util:: { def_id_of_def, is_local} ;
26+ use syntax:: ast_util:: { def_id_of_def, is_local, local_def } ;
2727use syntax:: attr;
2828use syntax:: parse:: token;
2929use syntax:: visit:: Visitor ;
3030use syntax:: visit;
3131
3232// Returns true if the given set of attributes contains the `#[inline]`
3333// attribute.
34- fn attributes_specify_inlining ( attrs : & [ Attribute ] ) -> bool {
34+ fn attributes_specify_inlining ( attrs : & [ ast :: Attribute ] ) -> bool {
3535 attr:: contains_name ( attrs, "inline" )
3636}
3737
3838// Returns true if the given set of generics implies that the item it's
3939// associated with must be inlined.
40- fn generics_require_inlining ( generics : & Generics ) -> bool {
40+ fn generics_require_inlining ( generics : & ast :: Generics ) -> bool {
4141 !generics. ty_params . is_empty ( )
4242}
4343
4444// Returns true if the given item must be inlined because it may be
4545// monomorphized or it was marked with `#[inline]`. This will only return
4646// true for functions.
47- fn item_might_be_inlined ( item: @item) -> bool {
47+ fn item_might_be_inlined ( item : @ast :: item ) -> bool {
4848 if attributes_specify_inlining ( item. attrs ) {
4949 return true
5050 }
5151
5252 match item. node {
53- item_fn( _, _, _, ref generics, _) => {
53+ ast :: item_fn( _, _, _, ref generics, _) => {
5454 generics_require_inlining ( generics)
5555 }
5656 _ => false ,
@@ -59,17 +59,17 @@ fn item_might_be_inlined(item: @item) -> bool {
5959
6060// Returns true if the given type method must be inlined because it may be
6161// monomorphized or it was marked with `#[inline]`.
62- fn ty_method_might_be_inlined ( ty_method : & TypeMethod ) -> bool {
62+ fn ty_method_might_be_inlined ( ty_method : & ast :: TypeMethod ) -> bool {
6363 attributes_specify_inlining ( ty_method. attrs ) ||
6464 generics_require_inlining ( & ty_method. generics )
6565}
6666
6767// Returns true if the given trait method must be inlined because it may be
6868// monomorphized or it was marked with `#[inline]`.
69- fn trait_method_might_be_inlined ( trait_method : & trait_method ) -> bool {
69+ fn trait_method_might_be_inlined ( trait_method : & ast :: trait_method ) -> bool {
7070 match * trait_method {
71- required( ref ty_method) => ty_method_might_be_inlined ( ty_method) ,
72- provided( _) => true
71+ ast :: required( ref ty_method) => ty_method_might_be_inlined ( ty_method) ,
72+ ast :: provided( _) => true
7373 }
7474}
7575
@@ -81,27 +81,27 @@ struct ReachableContext {
8181 // methods they've been resolved to.
8282 method_map : typeck:: method_map ,
8383 // The set of items which must be exported in the linkage sense.
84- reachable_symbols : @mut HashSet < NodeId > ,
84+ reachable_symbols : @mut HashSet < ast :: NodeId > ,
8585 // A worklist of item IDs. Each item ID in this worklist will be inlined
8686 // and will be scanned for further references.
87- worklist : @mut ~[ NodeId ] ,
87+ worklist : @mut ~[ ast :: NodeId ] ,
8888 // Known reexports of modules
8989 exp_map2 : resolve:: ExportMap2 ,
9090}
9191
9292struct MarkSymbolVisitor {
93- worklist : @mut ~[ NodeId ] ,
93+ worklist : @mut ~[ ast :: NodeId ] ,
9494 method_map : typeck:: method_map ,
9595 tcx : ty:: ctxt ,
96- reachable_symbols : @mut HashSet < NodeId > ,
96+ reachable_symbols : @mut HashSet < ast :: NodeId > ,
9797}
9898
9999impl Visitor < ( ) > for MarkSymbolVisitor {
100100
101- fn visit_expr ( & mut self , expr : @Expr , _: ( ) ) {
101+ fn visit_expr ( & mut self , expr : @ast :: Expr , _: ( ) ) {
102102
103103 match expr. node {
104- ExprPath ( _) => {
104+ ast :: ExprPath ( _) => {
105105 let def = match self . tcx . def_map . find ( & expr. id ) {
106106 Some ( & def) => def,
107107 None => {
@@ -118,7 +118,7 @@ impl Visitor<()> for MarkSymbolVisitor {
118118 }
119119 self . reachable_symbols . insert ( def_id. node ) ;
120120 }
121- ExprMethodCall ( * ) => {
121+ ast :: ExprMethodCall ( * ) => {
122122 match self . method_map . find ( & expr. id ) {
123123 Some ( & typeck:: method_map_entry {
124124 origin : typeck:: method_static( def_id) ,
@@ -162,24 +162,24 @@ impl ReachableContext {
162162
163163 // Returns true if the given def ID represents a local item that is
164164 // eligible for inlining and false otherwise.
165- fn def_id_represents_local_inlined_item ( tcx : ty:: ctxt , def_id : DefId )
165+ fn def_id_represents_local_inlined_item ( tcx : ty:: ctxt , def_id : ast :: DefId )
166166 -> bool {
167- if def_id. crate != LOCAL_CRATE {
167+ if def_id. crate != ast :: LOCAL_CRATE {
168168 return false
169169 }
170170
171171 let node_id = def_id. node ;
172172 match tcx. items . find ( & node_id) {
173173 Some ( & ast_map:: node_item( item, _) ) => {
174174 match item. node {
175- item_fn( * ) => item_might_be_inlined ( item) ,
175+ ast :: item_fn( * ) => item_might_be_inlined ( item) ,
176176 _ => false ,
177177 }
178178 }
179179 Some ( & ast_map:: node_trait_method( trait_method, _, _) ) => {
180180 match * trait_method {
181- required( _) => false ,
182- provided( _) => true ,
181+ ast :: required( _) => false ,
182+ ast :: provided( _) => true ,
183183 }
184184 }
185185 Some ( & ast_map:: node_method( method, impl_did, _) ) => {
@@ -189,11 +189,11 @@ impl ReachableContext {
189189 } else {
190190 // Check the impl. If the generics on the self type of the
191191 // impl require inlining, this method does too.
192- assert ! ( impl_did. crate == LOCAL_CRATE ) ;
192+ assert ! ( impl_did. crate == ast :: LOCAL_CRATE ) ;
193193 match tcx. items . find ( & impl_did. node ) {
194194 Some ( & ast_map:: node_item( item, _) ) => {
195195 match item. node {
196- item_impl( ref generics, _, _, _) => {
196+ ast :: item_impl( ref generics, _, _, _) => {
197197 generics_require_inlining ( generics)
198198 }
199199 _ => false
@@ -231,7 +231,7 @@ impl ReachableContext {
231231 }
232232 }
233233
234- fn propagate_mod ( & self , id : NodeId ) {
234+ fn propagate_mod ( & self , id : ast :: NodeId ) {
235235 match self . exp_map2 . find ( & id) {
236236 Some ( l) => {
237237 for reexport in l. iter ( ) {
@@ -262,21 +262,58 @@ impl ReachableContext {
262262 match self . tcx . items . find ( & search_item) {
263263 Some ( & ast_map:: node_item( item, _) ) => {
264264 match item. node {
265- item_fn( _, _, _, _, ref search_block) => {
265+ ast :: item_fn( _, _, _, _, ref search_block) => {
266266 visit:: walk_block ( & mut visitor, search_block, ( ) )
267267 }
268268 // Our recursion into modules involves looking up their
269269 // public reexports and the destinations of those
270270 // exports. Privacy will put them in the worklist, but
271271 // we won't find them in the ast_map, so this is where
272272 // we deal with publicly re-exported items instead.
273- item_mod( * ) => { self . propagate_mod ( item. id ) ; }
273+ ast:: item_mod( * ) => self . propagate_mod ( item. id ) ,
274+
275+ // Implementations of exported structs/enums need to get
276+ // added to the worklist (as all their methods should be
277+ // accessible)
278+ ast:: item_struct( * ) | ast:: item_enum( * ) => {
279+ let def = local_def ( item. id ) ;
280+ let impls = match self . tcx . inherent_impls . find ( & def) {
281+ Some ( & impls) => impls,
282+ None => continue
283+ } ;
284+ for imp in impls. iter ( ) {
285+ if is_local ( imp. did ) {
286+ self . worklist . push ( imp. did . node ) ;
287+ }
288+ }
289+ }
290+
291+ // Propagate through this impl
292+ ast:: item_impl( _, _, _, ref methods) => {
293+ for method in methods. iter ( ) {
294+ self . worklist . push ( method. id ) ;
295+ }
296+ }
297+
298+ // Default methods of exported traits need to all be
299+ // accessible.
300+ ast:: item_trait( _, _, ref methods) => {
301+ for method in methods. iter ( ) {
302+ match * method {
303+ ast:: required( * ) => { }
304+ ast:: provided( ref method) => {
305+ self . worklist . push ( method. id ) ;
306+ }
307+ }
308+ }
309+ }
310+
274311 // These are normal, nothing reachable about these
275312 // inherently and their children are already in the
276313 // worklist
277- item_struct ( * ) | item_impl ( * ) | item_static ( * ) |
278- item_enum ( * ) | item_ty ( * ) | item_trait ( * ) |
279- item_foreign_mod ( * ) => { }
314+ ast :: item_static ( * ) | ast :: item_ty ( * ) |
315+ ast :: item_foreign_mod ( * ) => { }
316+
280317 _ => {
281318 self . tcx . sess . span_bug ( item. span ,
282319 "found non-function item \
@@ -286,10 +323,10 @@ impl ReachableContext {
286323 }
287324 Some ( & ast_map:: node_trait_method( trait_method, _, _) ) => {
288325 match * trait_method {
289- required( * ) => {
326+ ast :: required( * ) => {
290327 // Keep going, nothing to get exported
291328 }
292- provided( ref method) => {
329+ ast :: provided( ref method) => {
293330 visit:: walk_block ( & mut visitor, & method. body , ( ) )
294331 }
295332 }
@@ -310,7 +347,7 @@ impl ReachableContext {
310347 worklist: {}",
311348 desc) )
312349 }
313- None if search_item == CRATE_NODE_ID => {
350+ None if search_item == ast :: CRATE_NODE_ID => {
314351 self . propagate_mod ( search_item) ;
315352 }
316353 None => {
@@ -329,7 +366,7 @@ impl ReachableContext {
329366 // reachability, which might result in a compile time loss.
330367 fn mark_destructors_reachable ( & self ) {
331368 for ( _, destructor_def_id) in self . tcx . destructor_for_type . iter ( ) {
332- if destructor_def_id. crate == LOCAL_CRATE {
369+ if destructor_def_id. crate == ast :: LOCAL_CRATE {
333370 self . reachable_symbols . insert ( destructor_def_id. node ) ;
334371 }
335372 }
@@ -340,7 +377,7 @@ pub fn find_reachable(tcx: ty::ctxt,
340377 method_map : typeck:: method_map ,
341378 exp_map2 : resolve:: ExportMap2 ,
342379 exported_items : & privacy:: ExportedItems )
343- -> @mut HashSet < NodeId > {
380+ -> @mut HashSet < ast :: NodeId > {
344381 // XXX(pcwalton): We only need to mark symbols that are exported. But this
345382 // is more complicated than just looking at whether the symbol is `pub`,
346383 // because it might be the target of a `pub use` somewhere. For now, I
0 commit comments