@@ -21,36 +21,36 @@ use middle::privacy;
21
21
use middle:: resolve;
22
22
23
23
use std:: hashmap:: HashSet ;
24
- use syntax:: ast:: * ;
24
+ use syntax:: ast;
25
25
use 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 } ;
27
27
use syntax:: attr;
28
28
use syntax:: parse:: token;
29
29
use syntax:: visit:: Visitor ;
30
30
use syntax:: visit;
31
31
32
32
// Returns true if the given set of attributes contains the `#[inline]`
33
33
// attribute.
34
- fn attributes_specify_inlining ( attrs : & [ Attribute ] ) -> bool {
34
+ fn attributes_specify_inlining ( attrs : & [ ast :: Attribute ] ) -> bool {
35
35
attr:: contains_name ( attrs, "inline" )
36
36
}
37
37
38
38
// Returns true if the given set of generics implies that the item it's
39
39
// associated with must be inlined.
40
- fn generics_require_inlining ( generics : & Generics ) -> bool {
40
+ fn generics_require_inlining ( generics : & ast :: Generics ) -> bool {
41
41
!generics. ty_params . is_empty ( )
42
42
}
43
43
44
44
// Returns true if the given item must be inlined because it may be
45
45
// monomorphized or it was marked with `#[inline]`. This will only return
46
46
// true for functions.
47
- fn item_might_be_inlined ( item: @item) -> bool {
47
+ fn item_might_be_inlined ( item : @ast :: item ) -> bool {
48
48
if attributes_specify_inlining ( item. attrs ) {
49
49
return true
50
50
}
51
51
52
52
match item. node {
53
- item_fn( _, _, _, ref generics, _) => {
53
+ ast :: item_fn( _, _, _, ref generics, _) => {
54
54
generics_require_inlining ( generics)
55
55
}
56
56
_ => false ,
@@ -59,17 +59,17 @@ fn item_might_be_inlined(item: @item) -> bool {
59
59
60
60
// Returns true if the given type method must be inlined because it may be
61
61
// 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 {
63
63
attributes_specify_inlining ( ty_method. attrs ) ||
64
64
generics_require_inlining ( & ty_method. generics )
65
65
}
66
66
67
67
// Returns true if the given trait method must be inlined because it may be
68
68
// 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 {
70
70
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
73
73
}
74
74
}
75
75
@@ -81,27 +81,27 @@ struct ReachableContext {
81
81
// methods they've been resolved to.
82
82
method_map : typeck:: method_map ,
83
83
// 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 > ,
85
85
// A worklist of item IDs. Each item ID in this worklist will be inlined
86
86
// and will be scanned for further references.
87
- worklist : @mut ~[ NodeId ] ,
87
+ worklist : @mut ~[ ast :: NodeId ] ,
88
88
// Known reexports of modules
89
89
exp_map2 : resolve:: ExportMap2 ,
90
90
}
91
91
92
92
struct MarkSymbolVisitor {
93
- worklist : @mut ~[ NodeId ] ,
93
+ worklist : @mut ~[ ast :: NodeId ] ,
94
94
method_map : typeck:: method_map ,
95
95
tcx : ty:: ctxt ,
96
- reachable_symbols : @mut HashSet < NodeId > ,
96
+ reachable_symbols : @mut HashSet < ast :: NodeId > ,
97
97
}
98
98
99
99
impl Visitor < ( ) > for MarkSymbolVisitor {
100
100
101
- fn visit_expr ( & mut self , expr : @Expr , _: ( ) ) {
101
+ fn visit_expr ( & mut self , expr : @ast :: Expr , _: ( ) ) {
102
102
103
103
match expr. node {
104
- ExprPath ( _) => {
104
+ ast :: ExprPath ( _) => {
105
105
let def = match self . tcx . def_map . find ( & expr. id ) {
106
106
Some ( & def) => def,
107
107
None => {
@@ -118,7 +118,7 @@ impl Visitor<()> for MarkSymbolVisitor {
118
118
}
119
119
self . reachable_symbols . insert ( def_id. node ) ;
120
120
}
121
- ExprMethodCall ( * ) => {
121
+ ast :: ExprMethodCall ( * ) => {
122
122
match self . method_map . find ( & expr. id ) {
123
123
Some ( & typeck:: method_map_entry {
124
124
origin : typeck:: method_static( def_id) ,
@@ -162,24 +162,24 @@ impl ReachableContext {
162
162
163
163
// Returns true if the given def ID represents a local item that is
164
164
// 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 )
166
166
-> bool {
167
- if def_id. crate != LOCAL_CRATE {
167
+ if def_id. crate != ast :: LOCAL_CRATE {
168
168
return false
169
169
}
170
170
171
171
let node_id = def_id. node ;
172
172
match tcx. items . find ( & node_id) {
173
173
Some ( & ast_map:: node_item( item, _) ) => {
174
174
match item. node {
175
- item_fn( * ) => item_might_be_inlined ( item) ,
175
+ ast :: item_fn( * ) => item_might_be_inlined ( item) ,
176
176
_ => false ,
177
177
}
178
178
}
179
179
Some ( & ast_map:: node_trait_method( trait_method, _, _) ) => {
180
180
match * trait_method {
181
- required( _) => false ,
182
- provided( _) => true ,
181
+ ast :: required( _) => false ,
182
+ ast :: provided( _) => true ,
183
183
}
184
184
}
185
185
Some ( & ast_map:: node_method( method, impl_did, _) ) => {
@@ -189,11 +189,11 @@ impl ReachableContext {
189
189
} else {
190
190
// Check the impl. If the generics on the self type of the
191
191
// impl require inlining, this method does too.
192
- assert ! ( impl_did. crate == LOCAL_CRATE ) ;
192
+ assert ! ( impl_did. crate == ast :: LOCAL_CRATE ) ;
193
193
match tcx. items . find ( & impl_did. node ) {
194
194
Some ( & ast_map:: node_item( item, _) ) => {
195
195
match item. node {
196
- item_impl( ref generics, _, _, _) => {
196
+ ast :: item_impl( ref generics, _, _, _) => {
197
197
generics_require_inlining ( generics)
198
198
}
199
199
_ => false
@@ -231,7 +231,7 @@ impl ReachableContext {
231
231
}
232
232
}
233
233
234
- fn propagate_mod ( & self , id : NodeId ) {
234
+ fn propagate_mod ( & self , id : ast :: NodeId ) {
235
235
match self . exp_map2 . find ( & id) {
236
236
Some ( l) => {
237
237
for reexport in l. iter ( ) {
@@ -262,21 +262,58 @@ impl ReachableContext {
262
262
match self . tcx . items . find ( & search_item) {
263
263
Some ( & ast_map:: node_item( item, _) ) => {
264
264
match item. node {
265
- item_fn( _, _, _, _, ref search_block) => {
265
+ ast :: item_fn( _, _, _, _, ref search_block) => {
266
266
visit:: walk_block ( & mut visitor, search_block, ( ) )
267
267
}
268
268
// Our recursion into modules involves looking up their
269
269
// public reexports and the destinations of those
270
270
// exports. Privacy will put them in the worklist, but
271
271
// we won't find them in the ast_map, so this is where
272
272
// 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
+
274
311
// These are normal, nothing reachable about these
275
312
// inherently and their children are already in the
276
313
// 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
+
280
317
_ => {
281
318
self . tcx . sess . span_bug ( item. span ,
282
319
"found non-function item \
@@ -286,10 +323,10 @@ impl ReachableContext {
286
323
}
287
324
Some ( & ast_map:: node_trait_method( trait_method, _, _) ) => {
288
325
match * trait_method {
289
- required( * ) => {
326
+ ast :: required( * ) => {
290
327
// Keep going, nothing to get exported
291
328
}
292
- provided( ref method) => {
329
+ ast :: provided( ref method) => {
293
330
visit:: walk_block ( & mut visitor, & method. body , ( ) )
294
331
}
295
332
}
@@ -310,7 +347,7 @@ impl ReachableContext {
310
347
worklist: {}",
311
348
desc) )
312
349
}
313
- None if search_item == CRATE_NODE_ID => {
350
+ None if search_item == ast :: CRATE_NODE_ID => {
314
351
self . propagate_mod ( search_item) ;
315
352
}
316
353
None => {
@@ -329,7 +366,7 @@ impl ReachableContext {
329
366
// reachability, which might result in a compile time loss.
330
367
fn mark_destructors_reachable ( & self ) {
331
368
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 {
333
370
self . reachable_symbols . insert ( destructor_def_id. node ) ;
334
371
}
335
372
}
@@ -340,7 +377,7 @@ pub fn find_reachable(tcx: ty::ctxt,
340
377
method_map : typeck:: method_map ,
341
378
exp_map2 : resolve:: ExportMap2 ,
342
379
exported_items : & privacy:: ExportedItems )
343
- -> @mut HashSet < NodeId > {
380
+ -> @mut HashSet < ast :: NodeId > {
344
381
// XXX(pcwalton): We only need to mark symbols that are exported. But this
345
382
// is more complicated than just looking at whether the symbol is `pub`,
346
383
// because it might be the target of a `pub use` somewhere. For now, I
0 commit comments