Skip to content

Mark allowed dead code and lang items as live #11471

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 12, 2014

Conversation

ktt3ja
Copy link
Contributor

@ktt3ja ktt3ja commented Jan 11, 2014

Dead code pass now explicitly checks for #[allow(dead_code)] and
#[lang=".."] attributes on items and marks them as live if they have
those attributes. The former is done so that if we want to suppress
warnings for a group of dead functions, we only have to annotate the
"root" of the call chain.

Close #11380 and #11440.

@@ -293,7 +294,7 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
default: warn
}),

("dead_code",
(dead_code_lint_str,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry about doing this...

@alexcrichton
Copy link
Member

nice work!

// Check from a list of attributes if it contains the appropriate
// `#[level(lintname)]` attribute (e.g. `#[allow(dead_code)]).
pub fn contains_lint(attrs: &[ast::Attribute],
level: level, lintname: &'static str) -> bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

each_lint seems to be more like an all(..) function whereas what I want to do is more along the line of an any(..) function, so I decided that it's more straightforward to write a separate contains_lint function.

@ktt3ja
Copy link
Contributor Author

ktt3ja commented Jan 11, 2014

r? @alexcrichton

Here's the diff of this commit from when you last reviewed it: http://ix.io/9Oy/diff

diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index ba810e5..52595d5 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -12,16 +12,16 @@
 // closely. The idea is that all reachable symbols are live, codes called
 // from live codes are live, and everything else is dead.

+use middle::lint::{allow, contains_lint, DeadCode};
+use middle::privacy;
 use middle::ty;
 use middle::typeck;
-use middle::privacy;
-use middle::lint::DeadCode;

 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::attr::AttrMetaMethods;
+use syntax::attr;
 use syntax::codemap;
 use syntax::parse::token;
 use syntax::visit::Visitor;
@@ -200,30 +200,22 @@ impl Visitor<()> for MarkSymbolVisitor {
 }

 fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
-    for attr in attrs.iter() {
-        if "allow" == attr.name() {
-            if attr.meta_item_list().is_none() {
-                continue
-            }
-            let list = attr.meta_item_list().unwrap();
-            for meta_item in list.iter() {
-                if dead_code_lint_str == meta_item.name() {
-                    return true;
-                }
-            }
-        } else if "lang" == attr.name() {
-            return true;
-        }
-    }
-    false
+    contains_lint(attrs, allow, dead_code_lint_str)
+    || attr::contains_name(attrs, "lang")
 }

 // This visitor seeds items that
-//   1) we want to explicitly consider as live:
+//   1) We want to explicitly consider as live:
 //     * Item annotated with #[allow(dead_code)]
+//         - This is done so that if we want to suppress warnings for a
+//           group of dead functions, we only have to annotate the "root".
+//           For example, if both `f` and `g` are dead and `f` calls `g`,
+//           then annotating `f` with `#[allow(dead_code)]` will suppress
+//           warning for both `f` and `g`.
 //     * Item annotated with #[lang=".."]
+//         - This is because lang items are always callable from elsewhere.
 //   or
-//   2) we are not sure to be live or not
+//   2) We are not sure to be live or not
 //     * Implementation of a trait method
 struct LifeSeeder {
     worklist: ~[ast::NodeId],
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index b468f35..59536c6 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -532,6 +532,8 @@ impl<'a> Context<'a> {
     }
 }

+// Check that every lint from the list of attributes satisfies `f`.
+// Return true if that's the case. Otherwise return false.
 pub fn each_lint(sess: session::Session,
                  attrs: &[ast::Attribute],
                  f: |@ast::MetaItem, level, @str| -> bool)
@@ -565,6 +567,25 @@ pub fn each_lint(sess: session::Session,
     true
 }

+// Check from a list of attributes if it contains the appropriate
+// `#[level(lintname)]` attribute (e.g. `#[allow(dead_code)]).
+pub fn contains_lint(attrs: &[ast::Attribute],
+                    level: level, lintname: &'static str) -> bool {
+    let level_name = level_to_str(level);
+    for attr in attrs.iter().filter(|m| level_name == m.name()) {
+        if attr.meta_item_list().is_none() {
+            continue
+        }
+        let list = attr.meta_item_list().unwrap();
+        for meta_item in list.iter() {
+            if lintname == meta_item.name() {
+                return true;
+            }
+        }
+    }
+    false
+}
+
 fn check_while_true_expr(cx: &Context, e: &ast::Expr) {
     match e.node {
         ast::ExprWhile(cond, _) => {
diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs
index a24b3ae..50c9d50 100644
--- a/src/test/compile-fail/lint-dead-code-3.rs
+++ b/src/test/compile-fail/lint-dead-code-3.rs
@@ -87,6 +87,6 @@ pub fn foo() {
 fn f() { g(); }
 fn g() {}

-// Similarly, lang items are live
-#[lang="fail_"]
+// Similarly, lang items are live (we use a dummy name here)
+#[lang="blah"]
 fn fail(_: *u8, _: *u8, _: uint) -> ! { loop {} }

use syntax::codemap;
use syntax::parse::token;
use syntax::visit::Visitor;
use syntax::visit;

pub static dead_code_lint_str: &'static str = "dead_code";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be DEAD_CODE_LINT_STR.

Dead code pass now explicitly checks for `#[allow(dead_code)]` and
`#[lang=".."]` attributes on items and marks them as live if they have
those attributes. The former is done so that if we want to suppress
warnings for a group of dead functions, we only have to annotate the
"root" of the call chain.
@ktt3ja
Copy link
Contributor Author

ktt3ja commented Jan 12, 2014

@alexcrichton: r+?

I didn't check for duplicate function name when I moved the tests over from lint-dead-code-3.rs to lint-dead-code-1.rs, so the test failed.

bors added a commit that referenced this pull request Jan 12, 2014
Dead code pass now explicitly checks for `#[allow(dead_code)]` and
`#[lang=".."]` attributes on items and marks them as live if they have
those attributes. The former is done so that if we want to suppress
warnings for a group of dead functions, we only have to annotate the
"root" of the call chain.

Close #11380 and #11440.
@bors bors closed this Jan 12, 2014
@bors bors merged commit deb3ca5 into rust-lang:master Jan 12, 2014
@ktt3ja ktt3ja deleted the issue-11380 branch January 12, 2014 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

allowing dead code should be transitive
4 participants