diff options
| author | Kiet Tran <ktt3ja@gmail.com> | 2013-12-08 02:55:27 -0500 |
|---|---|---|
| committer | Kiet Tran <ktt3ja@gmail.com> | 2013-12-08 02:55:27 -0500 |
| commit | c06dd0e0afb4b78ab4e482a7488adcf1c865bd19 (patch) | |
| tree | 4850d80648a57d527feda65f921bdf47940111f8 /src | |
| parent | 49b751dda19af57a2545a67879dd217e601b84c6 (diff) | |
| download | rust-c06dd0e0afb4b78ab4e482a7488adcf1c865bd19.tar.gz rust-c06dd0e0afb4b78ab4e482a7488adcf1c865bd19.zip | |
Add dead-code warning pass
Diffstat (limited to 'src')
33 files changed, 572 insertions, 53 deletions
diff --git a/src/etc/extract-tests.py b/src/etc/extract-tests.py index 5904e10a08d..ab2556f24c6 100644 --- a/src/etc/extract-tests.py +++ b/src/etc/extract-tests.py @@ -64,6 +64,7 @@ while cur < len(lines): #[ allow(dead_assignment) ];\n #[ allow(unused_mut) ];\n #[ allow(attribute_usage) ];\n +#[ allow(dead_code) ];\n #[ feature(macro_rules, globs, struct_variant, managed_boxes) ];\n """ + block if xfail: diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 63d6c60d269..e08726ad8a6 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -310,6 +310,10 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "reachability checking", (), |_| reachable::find_reachable(ty_cx, method_map, &exported_items)); + time(time_passes, "death checking", (), |_| + middle::dead::check_crate(ty_cx, method_map, + &exported_items, reachable_map, crate)); + time(time_passes, "lint checking", (), |_| lint::check_crate(ty_cx, &exported_items, crate)); @@ -510,19 +514,6 @@ pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &input, ppm: PpMode) { - fn ann_typed_post(tcx: ty::ctxt, node: pprust::ann_node) { - match node { - pprust::node_expr(s, expr) => { - pp::space(s.s); - pp::word(s.s, "as"); - pp::space(s.s); - pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))); - pprust::pclose(s); - } - _ => () - } - } - let crate = phase_1_parse_input(sess, cfg.clone(), input); let (crate, is_expanded) = match ppm { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7484550b3f3..2185617c79f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -77,6 +77,7 @@ pub mod middle { pub mod reachable; pub mod graph; pub mod cfg; + pub mod dead; } pub mod front { diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs new file mode 100644 index 00000000000..2327425c2ad --- /dev/null +++ b/src/librustc/middle/dead.rs @@ -0,0 +1,352 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This implements the dead-code warning pass. It follows middle::reachable +// closely. The idea is that all reachable symbols are live, codes called +// from live codes are live, and everything else is dead. + +use middle::ty; +use middle::typeck; +use middle::privacy; +use middle::lint::dead_code; + +use std::hashmap::HashSet; +use syntax::ast; +use syntax::ast_map; +use syntax::ast_util::{local_def, def_id_of_def, is_local}; +use syntax::codemap; +use syntax::parse::token; +use syntax::visit::Visitor; +use syntax::visit; + +// Any local node that may call something in its body block should be +// explored. For example, if it's a live node_item that is a +// function, then we should explore its block to check for codes that +// may need to be marked as live. +fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool { + if !is_local(def_id) { + return false; + } + match tcx.items.find(&def_id.node) { + Some(&ast_map::node_item(..)) + | Some(&ast_map::node_method(..)) + | Some(&ast_map::node_trait_method(..)) => true, + _ => false + } +} + +struct MarkSymbolVisitor { + worklist: ~[ast::NodeId], + method_map: typeck::method_map, + tcx: ty::ctxt, + live_symbols: ~HashSet<ast::NodeId>, +} + +impl MarkSymbolVisitor { + fn new(tcx: ty::ctxt, + method_map: typeck::method_map, + worklist: ~[ast::NodeId]) -> MarkSymbolVisitor { + MarkSymbolVisitor { + worklist: worklist, + method_map: method_map, + tcx: tcx, + live_symbols: ~HashSet::new(), + } + } + + fn lookup_and_handle_definition(&mut self, id: &ast::NodeId, + span: codemap::Span) { + let def = match self.tcx.def_map.find(id) { + Some(&def) => def, + None => self.tcx.sess.span_bug(span, "def ID not in def map?!"), + }; + let def_id = match def { + ast::DefVariant(enum_id, _, _) => Some(enum_id), + ast::DefPrimTy(_) => None, + _ => Some(def_id_of_def(def)), + }; + match def_id { + Some(def_id) => { + if should_explore(self.tcx, def_id) { + self.worklist.push(def_id.node); + } + self.live_symbols.insert(def_id.node); + } + None => (), + } + } + + fn mark_live_symbols(&mut self) { + let mut scanned = HashSet::new(); + while self.worklist.len() > 0 { + let id = self.worklist.pop(); + if scanned.contains(&id) { + continue + } + scanned.insert(id); + match self.tcx.items.find(&id) { + Some(node) => { + self.live_symbols.insert(id); + self.visit_node(node); + } + None => (), + } + } + } + + fn visit_node(&mut self, node: &ast_map::ast_node) { + match *node { + ast_map::node_item(item, _) => { + match item.node { + ast::item_fn(..) + | ast::item_ty(..) + | ast::item_static(..) + | ast::item_foreign_mod(_) => { + visit::walk_item(self, item, ()); + } + _ => () + } + } + ast_map::node_trait_method(trait_method, _, _) => { + visit::walk_trait_method(self, trait_method, ()); + } + ast_map::node_method(method, _, _) => { + visit::walk_block(self, method.body, ()); + } + _ => () + } + } +} + +impl Visitor<()> for MarkSymbolVisitor { + + fn visit_expr(&mut self, expr: @ast::Expr, _: ()) { + match expr.node { + ast::ExprPath(_) | ast::ExprStruct(..) => { + self.lookup_and_handle_definition(&expr.id, expr.span); + } + ast::ExprMethodCall(..) => { + match self.method_map.find(&expr.id) { + Some(&typeck::method_map_entry { + origin: typeck::method_static(def_id), + .. + }) => { + if should_explore(self.tcx, def_id) { + self.worklist.push(def_id.node); + } + self.live_symbols.insert(def_id.node); + } + Some(_) => (), + None => { + self.tcx.sess.span_bug(expr.span, + "method call expression not \ + in method map?!") + } + } + } + _ => () + } + + visit::walk_expr(self, expr, ()) + } + + fn visit_ty(&mut self, typ: &ast::Ty, _: ()) { + match typ.node { + ast::ty_path(_, _, ref id) => { + self.lookup_and_handle_definition(id, typ.span); + } + _ => visit::walk_ty(self, typ, ()), + } + } + + fn visit_item(&mut self, _item: @ast::item, _: ()) { + // Do not recurse into items. These items will be added to the + // worklist and recursed into manually if necessary. + } +} + +// This visitor is used to mark the implemented methods of a trait. Since we +// can not be sure if such methods are live or dead, we simply mark them +// as live. +struct TraitMethodSeeder { + worklist: ~[ast::NodeId], +} + +impl Visitor<()> for TraitMethodSeeder { + fn visit_item(&mut self, item: @ast::item, _: ()) { + match item.node { + ast::item_impl(_, Some(ref _trait_ref), _, ref methods) => { + for method in methods.iter() { + self.worklist.push(method.id); + } + } + ast::item_mod(..) | ast::item_fn(..) => { + visit::walk_item(self, item, ()); + } + _ => () + } + } +} + +fn create_and_seed_worklist(tcx: ty::ctxt, + exported_items: &privacy::ExportedItems, + reachable_symbols: &HashSet<ast::NodeId>, + crate: &ast::Crate) -> ~[ast::NodeId] { + let mut worklist = ~[]; + + // Preferably, we would only need to seed the worklist with reachable + // symbols. However, since the set of reachable symbols differs + // depending on whether a crate is built as bin or lib, and we want + // the warning to be consistent, we also seed the worklist with + // exported symbols. + for &id in exported_items.iter() { + worklist.push(id); + } + for &id in reachable_symbols.iter() { + worklist.push(id); + } + + // Seed entry point + match *tcx.sess.entry_fn { + Some((id, _)) => worklist.push(id), + None => () + } + + // Seed implemeneted trait methods + let mut trait_method_seeder = TraitMethodSeeder { + worklist: worklist + }; + visit::walk_crate(&mut trait_method_seeder, crate, ()); + + return trait_method_seeder.worklist; +} + +fn find_live(tcx: ty::ctxt, + method_map: typeck::method_map, + exported_items: &privacy::ExportedItems, + reachable_symbols: &HashSet<ast::NodeId>, + crate: &ast::Crate) + -> ~HashSet<ast::NodeId> { + let worklist = create_and_seed_worklist(tcx, exported_items, + reachable_symbols, crate); + let mut symbol_visitor = MarkSymbolVisitor::new(tcx, method_map, worklist); + symbol_visitor.mark_live_symbols(); + symbol_visitor.live_symbols +} + +fn should_warn(item: @ast::item) -> bool { + match item.node { + ast::item_static(..) + | ast::item_fn(..) + | ast::item_enum(..) + | ast::item_struct(..) => true, + _ => false + } +} + +fn get_struct_ctor_id(item: &ast::item) -> Option<ast::NodeId> { + match item.node { + ast::item_struct(struct_def, _) => struct_def.ctor_id, + _ => None + } +} + +struct DeadVisitor { + tcx: ty::ctxt, + live_symbols: ~HashSet<ast::NodeId>, +} + +impl DeadVisitor { + // id := node id of an item's definition. + // ctor_id := `Some` if the item is a struct_ctor (tuple struct), + // `None` otherwise. + // If the item is a struct_ctor, then either its `id` or + // `ctor_id` (unwrapped) is in the live_symbols set. More specifically, + // DefMap maps the ExprPath of a struct_ctor to the node referred by + // `ctor_id`. On the other hand, in a statement like + // `type <ident> <generics> = <ty>;` where <ty> refers to a struct_ctor, + // DefMap maps <ty> to `id` instead. + fn symbol_is_live(&mut self, id: ast::NodeId, + ctor_id: Option<ast::NodeId>) -> bool { + if self.live_symbols.contains(&id) + || ctor_id.map_default(false, + |ctor| self.live_symbols.contains(&ctor)) { + return true; + } + // If it's a type whose methods are live, then it's live, too. + // This is done to handle the case where, for example, the static + // method of a private type is used, but the type itself is never + // called directly. + let def_id = local_def(id); + match self.tcx.inherent_impls.find(&def_id) { + None => (), + Some(ref impl_list) => { + for impl_ in impl_list.iter() { + for method in impl_.methods.iter() { + if self.live_symbols.contains(&method.def_id.node) { + return true; + } + } + } + } + } + false + } +} + +impl Visitor<()> for DeadVisitor { + fn visit_item(&mut self, item: @ast::item, _: ()) { + let ctor_id = get_struct_ctor_id(item); + if !self.symbol_is_live(item.id, ctor_id) && should_warn(item) { + self.tcx.sess.add_lint(dead_code, item.id, item.span, + format!("code is never used: `{}`", + token::ident_to_str(&item.ident))); + } + visit::walk_item(self, item, ()); + } + + fn visit_fn(&mut self, fk: &visit::fn_kind, + _: &ast::fn_decl, block: ast::P<ast::Block>, + span: codemap::Span, id: ast::NodeId, _: ()) { + // Have to warn method here because methods are not ast::item + match *fk { + visit::fk_method(..) => { + let ident = visit::name_of_fn(fk); + if !self.symbol_is_live(id, None) { + self.tcx.sess + .add_lint(dead_code, id, span, + format!("code is never used: `{}`", + token::ident_to_str(&ident))); + } + } + _ => () + } + visit::walk_block(self, block, ()); + } + + // Overwrite so that we don't warn the trait method itself. + fn visit_trait_method(&mut self, trait_method :&ast::trait_method, _: ()) { + match *trait_method { + ast::provided(method) => visit::walk_block(self, method.body, ()), + ast::required(_) => () + } + } +} + +pub fn check_crate(tcx: ty::ctxt, + method_map: typeck::method_map, + exported_items: &privacy::ExportedItems, + reachable_symbols: &HashSet<ast::NodeId>, + crate: &ast::Crate) { + let live_symbols = find_live(tcx, method_map, exported_items, + reachable_symbols, crate); + let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols }; + visit::walk_crate(&mut visitor, crate, ()); +} diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 942d9b957ae..3e6803feadb 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -88,6 +88,7 @@ pub enum lint { dead_assignment, unused_mut, unnecessary_allocation, + dead_code, missing_doc, unreachable_code, @@ -282,6 +283,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[ default: warn }), + ("dead_code", + LintSpec { + lint: dead_code, + desc: "detect piece of code that will never be used", + default: warn + }), + ("missing_doc", LintSpec { lint: missing_doc, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4bb35457182..a6e45c7e1bb 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::{P, Block, Crate, DeclLocal, Expr_, ExprMac, SyntaxContext}; +use ast::{P, Block, Crate, DeclLocal, ExprMac, SyntaxContext}; use ast::{Local, Ident, mac_invoc_tt}; use ast::{item_mac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; use ast::{token_tree}; @@ -21,7 +21,6 @@ use codemap; use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use ext::base::*; use fold::*; -use opt_vec; use parse; use parse::{parse_item_from_source_str}; use parse::token; @@ -140,29 +139,6 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, let span = e.span; - fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_) - -> @ast::Expr { - @ast::Expr { - id: ast::DUMMY_NODE_ID, - node: node, - span: span, - } - } - - fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path { - ast::Path { - span: span, - global: false, - segments: ~[ - ast::PathSegment { - identifier: ident, - lifetimes: opt_vec::Empty, - types: opt_vec::Empty, - } - ], - } - } - // to: // // { @@ -714,14 +690,6 @@ pub fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold { } as @ast_fold } -// perform a bunch of renames -fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt { - folder.fold_stmt(&stmt) - .expect_one("renaming of stmt did not produce one stmt") -} - - - pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span { /* this discards information in the case of macro-defining macros */ Span { @@ -739,6 +707,7 @@ pub fn std_macros() -> @str { @r#"mod __std_macros { #[macro_escape]; #[doc(hidden)]; + #[allow(dead_code)]; macro_rules! ignore (($($x:tt)*) => (())) @@ -900,6 +869,7 @@ pub fn std_macros() -> @str { mod $c { #[allow(unused_imports)]; #[allow(non_uppercase_statics)]; + #[allow(dead_code)]; use super::*; @@ -979,12 +949,6 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess, injector.fold_crate(c) } -struct NoOpFolder { - contents: (), -} - -impl ast_fold for NoOpFolder {} - pub struct MacroExpander { extsbox: @mut SyntaxEnv, cx: @ExtCtxt, diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index f6fb521ff7c..9193a9cee17 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -331,7 +331,12 @@ impl Context { let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant"); let unnamed = self.ecx.attribute(self.fmtsp, unnamed); - return ~[unnamed]; + // Do not warn format string as dead code + let dead_code = self.ecx.meta_word(self.fmtsp, @"dead_code"); + let allow_dead_code = self.ecx.meta_list(self.fmtsp, + @"allow", ~[dead_code]); + let allow_dead_code = self.ecx.attribute(self.fmtsp, allow_dead_code); + return ~[unnamed, allow_dead_code]; } /// Translate a `parse::Piece` to a static `rt::Piece` diff --git a/src/test/compile-fail/issue-2150.rs b/src/test/compile-fail/issue-2150.rs index 64344ab4277..2c54b622021 100644 --- a/src/test/compile-fail/issue-2150.rs +++ b/src/test/compile-fail/issue-2150.rs @@ -10,6 +10,7 @@ #[deny(unreachable_code)]; #[allow(unused_variable)]; +#[allow(dead_code)]; fn fail_len(v: ~[int]) -> uint { let mut i = 3; diff --git a/src/test/compile-fail/issue-6804.rs b/src/test/compile-fail/issue-6804.rs index c2e0c40d8ca..23d9f3199c1 100644 --- a/src/test/compile-fail/issue-6804.rs +++ b/src/test/compile-fail/issue-6804.rs @@ -1,3 +1,5 @@ +#[allow(dead_code)]; + // Matching against NaN should result in a warning use std::f64::NAN; diff --git a/src/test/compile-fail/issue-7246.rs b/src/test/compile-fail/issue-7246.rs index dacc31a573a..ce31ac2e8fa 100644 --- a/src/test/compile-fail/issue-7246.rs +++ b/src/test/compile-fail/issue-7246.rs @@ -9,6 +9,8 @@ // except according to those terms. #[deny(unreachable_code)]; +#[allow(dead_code)]; + use std::ptr; pub unsafe fn g() { return; diff --git a/src/test/compile-fail/lint-change-warnings.rs b/src/test/compile-fail/lint-change-warnings.rs index 977abc4dc0d..e9985430adf 100644 --- a/src/test/compile-fail/lint-change-warnings.rs +++ b/src/test/compile-fail/lint-change-warnings.rs @@ -9,6 +9,7 @@ // except according to those terms. #[deny(warnings)]; +#[allow(dead_code)]; fn main() { while true {} //~ ERROR: infinite diff --git a/src/test/compile-fail/lint-ctypes-enum.rs b/src/test/compile-fail/lint-ctypes-enum.rs index 857e3bb4b8d..2e47695f0fc 100644 --- a/src/test/compile-fail/lint-ctypes-enum.rs +++ b/src/test/compile-fail/lint-ctypes-enum.rs @@ -9,6 +9,7 @@ // except according to those terms. #[deny(ctypes)]; +#[allow(dead_code)]; enum Z { } enum U { A } diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs new file mode 100644 index 00000000000..7d7cbce6e89 --- /dev/null +++ b/src/test/compile-fail/lint-dead-code-1.rs @@ -0,0 +1,69 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unused_variable)]; +#[deny(dead_code)]; + +#[crate_type="lib"]; + +pub use foo2::Bar2; +mod foo { + pub struct Bar; //~ ERROR: code is never used +} + +mod foo2 { + pub struct Bar2; +} + +pub static pub_static: int = 0; +static priv_static: int = 0; //~ ERROR: code is never used +static used_static: int = 0; +pub static used_static2: int = used_static; + +pub fn pub_fn() { + used_fn(); + let used_struct1 = UsedStruct1 { x: 1 }; + let used_struct2 = UsedStruct2(1); + let used_struct3 = UsedStruct3; + let e = foo3; + SemiUsedStruct::la_la_la(); + +} +fn priv_fn() { //~ ERROR: code is never used + let unused_struct = PrivStruct; +} +fn used_fn() {} + +pub type typ = ~UsedStruct4; +pub struct PubStruct(); +struct PrivStruct; //~ ERROR: code is never used +struct UsedStruct1 { x: int } +struct UsedStruct2(int); +struct UsedStruct3; +struct UsedStruct4; +// this struct is never used directly, but its method is, so we don't want +// to warn it +struct SemiUsedStruct; +impl SemiUsedStruct { + fn la_la_la() {} +} + +pub enum pub_enum { foo1, bar1 } +enum priv_enum { foo2, bar2 } //~ ERROR: code is never used +enum used_enum { foo3, bar3 } + +fn foo() { //~ ERROR: code is never used + bar(); + let unused_enum = foo2; +} + +fn bar() { //~ ERROR: code is never used + foo(); +} diff --git a/src/test/compile-fail/lint-dead-code-2.rs b/src/test/compile-fail/lint-dead-code-2.rs new file mode 100644 index 00000000000..663e7890bbe --- /dev/null +++ b/src/test/compile-fail/lint-dead-code-2.rs @@ -0,0 +1,50 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unused_variable)]; +#[deny(dead_code)]; + +struct Foo; + +trait Bar { + fn bar1(&self); + fn bar2(&self) { + self.bar1(); + } +} + +impl Bar for Foo { + fn bar1(&self) { + live_fn(); + } +} + +fn live_fn() {} + +fn dead_fn() {} //~ ERROR: code is never used + +#[main] +fn dead_fn2() {} //~ ERROR: code is never used + +fn used_fn() {} + +#[start] +fn start(_: int, _: **u8) -> int { + used_fn(); + let foo = Foo; + foo.bar2(); + 0 +} + +// this is not main +fn main() { //~ ERROR: code is never used + dead_fn(); + dead_fn2(); +} diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs new file mode 100644 index 00000000000..8a5f239ed05 --- /dev/null +++ b/src/test/compile-fail/lint-dead-code-3.rs @@ -0,0 +1,50 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(unused_variable)]; +#[deny(dead_code)]; + +#[crate_type="lib"]; + +struct Foo; //~ ERROR: code is never used +impl Foo { + fn foo(&self) { //~ ERROR: code is never used + bar() + } +} + +fn bar() { //~ ERROR: code is never used + fn baz() {} //~ ERROR: code is never used + + Foo.foo(); + baz(); +} + +// no warning +struct Foo2; +impl Foo2 { fn foo2(&self) { bar2() } } +fn bar2() { + fn baz2() {} + + Foo2.foo2(); + baz2(); +} + +pub fn pub_fn() { + let foo2_struct = Foo2; + foo2_struct.foo2(); +} + +// not warned because it's used in the parameter of `free` below +enum c_void {} + +extern { + fn free(p: *c_void); +} diff --git a/src/test/compile-fail/lint-heap-memory.rs b/src/test/compile-fail/lint-heap-memory.rs index fadda4173a6..b550c227898 100644 --- a/src/test/compile-fail/lint-heap-memory.rs +++ b/src/test/compile-fail/lint-heap-memory.rs @@ -10,6 +10,7 @@ #[feature(managed_boxes)]; #[forbid(heap_memory)]; +#[allow(dead_code)]; struct Foo { x: @int //~ ERROR type uses managed diff --git a/src/test/compile-fail/lint-impl-fn.rs b/src/test/compile-fail/lint-impl-fn.rs index 3cc0495206d..ad35a22b4ef 100644 --- a/src/test/compile-fail/lint-impl-fn.rs +++ b/src/test/compile-fail/lint-impl-fn.rs @@ -9,6 +9,7 @@ // except according to those terms. #[allow(while_true)]; +#[allow(dead_code)]; struct A(int); diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 12d9cbe0dbc..a083948bf84 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -13,6 +13,7 @@ #[feature(struct_variant)]; #[feature(globs)]; #[deny(missing_doc)]; +#[allow(dead_code)]; //! Some garbage docs for the crate here #[doc="More garbage"]; diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index 2cabdfe5bb0..6d217656cd0 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -9,6 +9,7 @@ // except according to those terms. #[forbid(non_camel_case_types)]; +#[allow(dead_code)]; struct foo { //~ ERROR type `foo` should have a camel case identifier bar: int, diff --git a/src/test/compile-fail/lint-non-uppercase-statics.rs b/src/test/compile-fail/lint-non-uppercase-statics.rs index 4da4d3ada38..d41a4ccda8d 100644 --- a/src/test/compile-fail/lint-non-uppercase-statics.rs +++ b/src/test/compile-fail/lint-non-uppercase-statics.rs @@ -9,6 +9,7 @@ // except according to those terms. #[forbid(non_uppercase_statics)]; +#[allow(dead_code)]; static foo: int = 1; //~ ERROR static constant should have an uppercase identifier diff --git a/src/test/compile-fail/lint-obsolete-attr.rs b/src/test/compile-fail/lint-obsolete-attr.rs index 91976978315..442bcaa0923 100644 --- a/src/test/compile-fail/lint-obsolete-attr.rs +++ b/src/test/compile-fail/lint-obsolete-attr.rs @@ -12,6 +12,7 @@ // injected intrinsics by the compiler. #[deny(attribute_usage)]; +#[allow(dead_code)]; #[abi="stdcall"] extern {} //~ ERROR: obsolete attribute diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 1046a638ff9..9cc06cc5395 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -15,6 +15,7 @@ #[deny(unstable)]; #[deny(deprecated)]; #[deny(experimental)]; +#[allow(dead_code)]; mod cross_crate { extern mod lint_stability; diff --git a/src/test/compile-fail/lint-type-limits.rs b/src/test/compile-fail/lint-type-limits.rs index 08714e3a044..f609debb5bd 100644 --- a/src/test/compile-fail/lint-type-limits.rs +++ b/src/test/compile-fail/lint-type-limits.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(dead_code)]; + // compile-flags: -D type-limits fn main() { } diff --git a/src/test/compile-fail/lint-unsafe-block.rs b/src/test/compile-fail/lint-unsafe-block.rs index 7f3075e90bc..529d3e921a0 100644 --- a/src/test/compile-fail/lint-unsafe-block.rs +++ b/src/test/compile-fail/lint-unsafe-block.rs @@ -9,6 +9,7 @@ // except according to those terms. #[allow(unused_unsafe)]; +#[allow(dead_code)]; #[deny(unsafe_block)]; #[feature(macro_rules)]; diff --git a/src/test/compile-fail/lint-unused-import-tricky-globs.rs b/src/test/compile-fail/lint-unused-import-tricky-globs.rs index 85edbd1d147..9d6140b8fd2 100644 --- a/src/test/compile-fail/lint-unused-import-tricky-globs.rs +++ b/src/test/compile-fail/lint-unused-import-tricky-globs.rs @@ -10,6 +10,7 @@ #[feature(globs)]; #[deny(unused_imports)]; +#[allow(dead_code)]; mod A { pub fn p() {} diff --git a/src/test/compile-fail/lint-unused-import-tricky-names.rs b/src/test/compile-fail/lint-unused-import-tricky-names.rs index 0347c673779..24511296a0b 100644 --- a/src/test/compile-fail/lint-unused-import-tricky-names.rs +++ b/src/test/compile-fail/lint-unused-import-tricky-names.rs @@ -9,6 +9,7 @@ // except according to those terms. #[deny(unused_imports)]; +#[allow(dead_code)]; // Regression test for issue #6633 mod issue6633 { diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs index 9bb58453539..e248184d5e2 100644 --- a/src/test/compile-fail/lint-unused-imports.rs +++ b/src/test/compile-fail/lint-unused-imports.rs @@ -10,6 +10,7 @@ #[feature(globs)]; #[deny(unused_imports)]; +#[allow(dead_code)]; use cal = bar::c::cc; diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 798c1194af8..271aedd3f6a 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -12,6 +12,7 @@ #[allow(dead_assignment)]; #[allow(unused_variable)]; +#[allow(dead_code)]; #[deny(unused_mut)]; fn main() { diff --git a/src/test/compile-fail/lint-unused-unsafe.rs b/src/test/compile-fail/lint-unused-unsafe.rs index f28322d3bf7..96a4c2adca3 100644 --- a/src/test/compile-fail/lint-unused-unsafe.rs +++ b/src/test/compile-fail/lint-unused-unsafe.rs @@ -10,6 +10,7 @@ // Exercise the unused_unsafe attribute in some positive and negative cases +#[allow(dead_code)]; #[deny(unused_unsafe)]; mod foo { diff --git a/src/test/compile-fail/liveness-dead.rs b/src/test/compile-fail/liveness-dead.rs index df78b25187b..a3d388d7c34 100644 --- a/src/test/compile-fail/liveness-dead.rs +++ b/src/test/compile-fail/liveness-dead.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(dead_code)]; #[deny(dead_assignment)]; fn f1(x: &mut int) { diff --git a/src/test/compile-fail/match-static-const-lc.rs b/src/test/compile-fail/match-static-const-lc.rs index 1cdceaca6b4..fd605b79dbe 100644 --- a/src/test/compile-fail/match-static-const-lc.rs +++ b/src/test/compile-fail/match-static-const-lc.rs @@ -10,6 +10,7 @@ // Issue #7526: lowercase static constants in patterns look like bindings +#[allow(dead_code)]; #[deny(non_uppercase_pattern_statics)]; pub static a : int = 97; diff --git a/src/test/compile-fail/static-assert.rs b/src/test/compile-fail/static-assert.rs index 019a4b88aed..4f7f7dd7408 100644 --- a/src/test/compile-fail/static-assert.rs +++ b/src/test/compile-fail/static-assert.rs @@ -1,3 +1,5 @@ +#[allow(dead_code)]; + #[static_assert] static A: bool = false; //~ ERROR static assertion failed diff --git a/src/test/compile-fail/static-assert2.rs b/src/test/compile-fail/static-assert2.rs index 42e475dac8b..ceaa3889179 100644 --- a/src/test/compile-fail/static-assert2.rs +++ b/src/test/compile-fail/static-assert2.rs @@ -1,3 +1,5 @@ +#[allow(dead_code)]; + #[static_assert] static E: bool = 1 == 2; //~ ERROR static assertion failed |
