|
12 | 12 | // closely. The idea is that all reachable symbols are live, codes called
|
13 | 13 | // from live codes are live, and everything else is dead.
|
14 | 14 |
|
| 15 | +use middle::lint::{allow, contains_lint, DeadCode}; |
| 16 | +use middle::privacy; |
15 | 17 | use middle::ty;
|
16 | 18 | use middle::typeck;
|
17 |
| -use middle::privacy; |
18 |
| -use middle::lint::DeadCode; |
19 | 19 |
|
20 | 20 | use std::hashmap::HashSet;
|
21 | 21 | use syntax::ast;
|
22 | 22 | use syntax::ast_map;
|
23 | 23 | use syntax::ast_util::{local_def, def_id_of_def, is_local};
|
| 24 | +use syntax::attr; |
24 | 25 | use syntax::codemap;
|
25 | 26 | use syntax::parse::token;
|
26 | 27 | use syntax::visit::Visitor;
|
27 | 28 | use syntax::visit;
|
28 | 29 |
|
| 30 | +pub static DEAD_CODE_LINT_STR: &'static str = "dead_code"; |
| 31 | + |
29 | 32 | // Any local node that may call something in its body block should be
|
30 | 33 | // explored. For example, if it's a live NodeItem that is a
|
31 | 34 | // function, then we should explore its block to check for codes that
|
@@ -196,26 +199,57 @@ impl Visitor<()> for MarkSymbolVisitor {
|
196 | 199 | }
|
197 | 200 | }
|
198 | 201 |
|
199 |
| -// This visitor is used to mark the implemented methods of a trait. Since we |
200 |
| -// can not be sure if such methods are live or dead, we simply mark them |
201 |
| -// as live. |
202 |
| -struct TraitMethodSeeder { |
| 202 | +fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { |
| 203 | + contains_lint(attrs, allow, DEAD_CODE_LINT_STR) |
| 204 | + || attr::contains_name(attrs, "lang") |
| 205 | +} |
| 206 | + |
| 207 | +// This visitor seeds items that |
| 208 | +// 1) We want to explicitly consider as live: |
| 209 | +// * Item annotated with #[allow(dead_code)] |
| 210 | +// - This is done so that if we want to suppress warnings for a |
| 211 | +// group of dead functions, we only have to annotate the "root". |
| 212 | +// For example, if both `f` and `g` are dead and `f` calls `g`, |
| 213 | +// then annotating `f` with `#[allow(dead_code)]` will suppress |
| 214 | +// warning for both `f` and `g`. |
| 215 | +// * Item annotated with #[lang=".."] |
| 216 | +// - This is because lang items are always callable from elsewhere. |
| 217 | +// or |
| 218 | +// 2) We are not sure to be live or not |
| 219 | +// * Implementation of a trait method |
| 220 | +struct LifeSeeder { |
203 | 221 | worklist: ~[ast::NodeId],
|
204 | 222 | }
|
205 | 223 |
|
206 |
| -impl Visitor<()> for TraitMethodSeeder { |
| 224 | +impl Visitor<()> for LifeSeeder { |
207 | 225 | fn visit_item(&mut self, item: &ast::Item, _: ()) {
|
| 226 | + if has_allow_dead_code_or_lang_attr(item.attrs) { |
| 227 | + self.worklist.push(item.id); |
| 228 | + } |
208 | 229 | match item.node {
|
209 | 230 | ast::ItemImpl(_, Some(ref _trait_ref), _, ref methods) => {
|
210 | 231 | for method in methods.iter() {
|
211 | 232 | self.worklist.push(method.id);
|
212 | 233 | }
|
213 | 234 | }
|
214 |
| - ast::ItemMod(..) | ast::ItemFn(..) => { |
215 |
| - visit::walk_item(self, item, ()); |
| 235 | + _ => () |
| 236 | + } |
| 237 | + visit::walk_item(self, item, ()); |
| 238 | + } |
| 239 | + |
| 240 | + fn visit_fn(&mut self, fk: &visit::FnKind, |
| 241 | + _: &ast::FnDecl, block: &ast::Block, |
| 242 | + _: codemap::Span, id: ast::NodeId, _: ()) { |
| 243 | + // Check for method here because methods are not ast::Item |
| 244 | + match *fk { |
| 245 | + visit::FkMethod(_, _, method) => { |
| 246 | + if has_allow_dead_code_or_lang_attr(method.attrs) { |
| 247 | + self.worklist.push(id); |
| 248 | + } |
216 | 249 | }
|
217 | 250 | _ => ()
|
218 | 251 | }
|
| 252 | + visit::walk_block(self, block, ()); |
219 | 253 | }
|
220 | 254 | }
|
221 | 255 |
|
@@ -244,12 +278,12 @@ fn create_and_seed_worklist(tcx: ty::ctxt,
|
244 | 278 | }
|
245 | 279 |
|
246 | 280 | // Seed implemeneted trait methods
|
247 |
| - let mut trait_method_seeder = TraitMethodSeeder { |
| 281 | + let mut life_seeder = LifeSeeder { |
248 | 282 | worklist: worklist
|
249 | 283 | };
|
250 |
| - visit::walk_crate(&mut trait_method_seeder, crate, ()); |
| 284 | + visit::walk_crate(&mut life_seeder, crate, ()); |
251 | 285 |
|
252 |
| - return trait_method_seeder.worklist; |
| 286 | + return life_seeder.worklist; |
253 | 287 | }
|
254 | 288 |
|
255 | 289 | fn find_live(tcx: ty::ctxt,
|
|
0 commit comments