@@ -50,6 +50,7 @@ fn item_might_be_inlined(item: @ast::item) -> bool {
50
50
}
51
51
52
52
match item. node {
53
+ ast:: item_impl( ref generics, _, _, _) |
53
54
ast:: item_fn( _, _, _, ref generics, _) => {
54
55
generics_require_inlining ( generics)
55
56
}
@@ -64,6 +65,25 @@ fn ty_method_might_be_inlined(ty_method: &ast::TypeMethod) -> bool {
64
65
generics_require_inlining ( & ty_method. generics )
65
66
}
66
67
68
+ fn method_might_be_inlined ( tcx : ty:: ctxt , method : & ast:: method ,
69
+ impl_src : ast:: DefId ) -> bool {
70
+ if attributes_specify_inlining ( method. attrs ) ||
71
+ generics_require_inlining ( & method. generics ) {
72
+ return true
73
+ }
74
+ if is_local ( impl_src) {
75
+ match tcx. items . find ( & impl_src. node ) {
76
+ Some ( & ast_map:: node_item( item, _) ) => item_might_be_inlined ( item) ,
77
+ Some ( * ) | None => {
78
+ tcx. sess . span_bug ( method. span , "impl did is not an item" )
79
+ }
80
+ }
81
+ } else {
82
+ tcx. sess . span_bug ( method. span , "found a foreign impl as a parent of a \
83
+ local method")
84
+ }
85
+ }
86
+
67
87
// Returns true if the given trait method must be inlined because it may be
68
88
// monomorphized or it was marked with `#[inline]`.
69
89
fn trait_method_might_be_inlined ( trait_method : & ast:: trait_method ) -> bool {
@@ -100,50 +120,54 @@ impl Visitor<()> for MarkSymbolVisitor {
100
120
101
121
fn visit_expr ( & mut self , expr : @ast:: Expr , _: ( ) ) {
102
122
103
- match expr. node {
104
- ast:: ExprPath ( _) => {
105
- let def = match self . tcx . def_map . find ( & expr. id ) {
106
- Some ( & def) => def,
107
- None => {
108
- self . tcx . sess . span_bug ( expr. span ,
109
- "def ID not in def map?!" )
110
- }
111
- } ;
123
+ match expr. node {
124
+ ast:: ExprPath ( _) => {
125
+ let def = match self . tcx . def_map . find ( & expr. id ) {
126
+ Some ( & def) => def,
127
+ None => {
128
+ self . tcx . sess . span_bug ( expr. span ,
129
+ "def ID not in def map?!" )
130
+ }
131
+ } ;
112
132
113
- let def_id = def_id_of_def ( def) ;
133
+ let def_id = def_id_of_def ( def) ;
134
+ if ReachableContext ::
135
+ def_id_represents_local_inlined_item ( self . tcx , def_id) {
136
+ self . worklist . push ( def_id. node )
137
+ }
138
+ self . reachable_symbols . insert ( def_id. node ) ;
139
+ }
140
+ ast:: ExprMethodCall ( * ) => {
141
+ match self . method_map . find ( & expr. id ) {
142
+ Some ( & typeck:: method_map_entry {
143
+ origin : typeck:: method_static( def_id) ,
144
+ _
145
+ } ) => {
114
146
if ReachableContext ::
115
- def_id_represents_local_inlined_item ( self . tcx ,
116
- def_id) {
117
- self . worklist . push ( def_id. node )
118
- }
147
+ def_id_represents_local_inlined_item (
148
+ self . tcx ,
149
+ def_id) {
150
+ self . worklist . push ( def_id. node )
151
+ }
119
152
self . reachable_symbols . insert ( def_id. node ) ;
120
153
}
121
- ast:: ExprMethodCall ( * ) => {
122
- match self . method_map . find ( & expr. id ) {
123
- Some ( & typeck:: method_map_entry {
124
- origin : typeck:: method_static( def_id) ,
125
- _
126
- } ) => {
127
- if ReachableContext ::
128
- def_id_represents_local_inlined_item (
129
- self . tcx ,
130
- def_id) {
131
- self . worklist . push ( def_id. node )
132
- }
133
- self . reachable_symbols . insert ( def_id. node ) ;
134
- }
135
- Some ( _) => { }
136
- None => {
137
- self . tcx . sess . span_bug ( expr. span ,
138
- "method call expression \
154
+ Some ( _) => { }
155
+ None => {
156
+ self . tcx . sess . span_bug ( expr. span ,
157
+ "method call expression \
139
158
not in method map?!")
140
- }
141
- }
142
159
}
143
- _ => { }
144
160
}
161
+ }
162
+ _ => { }
163
+ }
145
164
146
- visit:: walk_expr ( self , expr, ( ) )
165
+ visit:: walk_expr ( self , expr, ( ) )
166
+ }
167
+
168
+ fn visit_item ( & mut self , _item : @ast:: item , _: ( ) ) {
169
+ // Do not recurse into items. These items will be added to the worklist
170
+ // and recursed into manually if necessary.
147
171
}
148
172
}
149
173
@@ -263,8 +287,11 @@ impl ReachableContext {
263
287
Some ( & ast_map:: node_item( item, _) ) => {
264
288
match item. node {
265
289
ast:: item_fn( _, _, _, _, ref search_block) => {
266
- visit:: walk_block ( & mut visitor, search_block, ( ) )
290
+ if item_might_be_inlined ( item) {
291
+ visit:: walk_block ( & mut visitor, search_block, ( ) )
292
+ }
267
293
}
294
+
268
295
// Our recursion into modules involves looking up their
269
296
// public reexports and the destinations of those
270
297
// exports. Privacy will put them in the worklist, but
@@ -331,8 +358,10 @@ impl ReachableContext {
331
358
}
332
359
}
333
360
}
334
- Some ( & ast_map:: node_method( ref method, _, _) ) => {
335
- visit:: walk_block ( & mut visitor, & method. body , ( ) )
361
+ Some ( & ast_map:: node_method( method, did, _) ) => {
362
+ if method_might_be_inlined ( self . tcx , method, did) {
363
+ visit:: walk_block ( & mut visitor, & method. body , ( ) )
364
+ }
336
365
}
337
366
// Nothing to recurse on for these
338
367
Some ( & ast_map:: node_foreign_item( * ) ) |
@@ -378,17 +407,6 @@ pub fn find_reachable(tcx: ty::ctxt,
378
407
exp_map2 : resolve:: ExportMap2 ,
379
408
exported_items : & privacy:: ExportedItems )
380
409
-> @mut HashSet < ast:: NodeId > {
381
- // XXX(pcwalton): We only need to mark symbols that are exported. But this
382
- // is more complicated than just looking at whether the symbol is `pub`,
383
- // because it might be the target of a `pub use` somewhere. For now, I
384
- // think we are fine, because you can't `pub use` something that wasn't
385
- // exported due to the bug whereby `use` only looks through public
386
- // modules even if you're inside the module the `use` appears in. When
387
- // this bug is fixed, however, this code will need to be updated. Probably
388
- // the easiest way to fix this (although a conservative overapproximation)
389
- // is to have the name resolution pass mark all targets of a `pub use` as
390
- // "must be reachable".
391
-
392
410
let reachable_context = ReachableContext :: new ( tcx, method_map, exp_map2) ;
393
411
394
412
// Step 1: Seed the worklist with all nodes which were found to be public as
0 commit comments