-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add lint for unused macros #41907
Add lint for unused macros #41907
Changes from 6 commits
df188b8
db82c57
d14d194
ba0601d
b36d23c
0d0cb27
25b7f10
6dbd706
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1195,6 +1195,12 @@ pub struct Resolver<'a> { | |
pub whitelisted_legacy_custom_derives: Vec<Name>, | ||
pub found_unresolved_macro: bool, | ||
|
||
// List of macros that we need to warn about as being unused. | ||
// The bool is true if the macro is unused, and false if its used. | ||
// Setting a bool to false should be much faster than removing a single | ||
// element from a FxHashSet. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you clarify that this is only for crate-local There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, but hopefully the upcoming macros 2.0 macros could be included as well. |
||
unused_macros: FxHashMap<DefId, bool>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think this should be an |
||
|
||
// Maps the `Mark` of an expansion to its containing module or block. | ||
invocations: FxHashMap<Mark, &'a InvocationData<'a>>, | ||
|
||
|
@@ -1400,6 +1406,7 @@ impl<'a> Resolver<'a> { | |
potentially_unused_imports: Vec::new(), | ||
struct_constructors: DefIdMap(), | ||
found_unresolved_macro: false, | ||
unused_macros: FxHashMap(), | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,7 +16,7 @@ use resolve_imports::ImportResolver; | |
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex}; | ||
use rustc::hir::def::{Def, Export}; | ||
use rustc::hir::map::{self, DefCollector}; | ||
use rustc::ty; | ||
use rustc::{ty, lint}; | ||
use syntax::ast::{self, Name, Ident}; | ||
use syntax::attr::{self, HasAttrs}; | ||
use syntax::errors::DiagnosticBuilder; | ||
|
@@ -291,12 +291,32 @@ impl<'a> base::Resolver for Resolver<'a> { | |
}, | ||
}; | ||
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id()); | ||
self.unused_macros.get_mut(&def.def_id()).map(|m| *m = false); | ||
Ok(Some(self.get_macro(def))) | ||
} | ||
|
||
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) | ||
-> Result<Rc<SyntaxExtension>, Determinacy> { | ||
self.resolve_macro_to_def(scope, path, kind, force).map(|def| self.get_macro(def)) | ||
self.resolve_macro_to_def(scope, path, kind, force).map(|def| { | ||
self.unused_macros.get_mut(&def.def_id()).map(|m| *m = false); | ||
self.get_macro(def) | ||
}) | ||
} | ||
|
||
fn check_unused_macros(&self) { | ||
for (did, _) in self.unused_macros.iter().filter(|&(_, b)| *b) { | ||
let id_span = match *self.macro_map[did] { | ||
SyntaxExtension::NormalTT(_, isp, _) => isp, | ||
_ => None | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this is usually formatted let id_span = match *self.macro_map[did] {
SyntaxExtension::NormalTT(_, isp, _) => isp,
_ => None
}; |
||
if let Some((id, span)) = id_span { | ||
let lint = lint::builtin::UNUSED_MACROS; | ||
let msg = "unused macro definition".to_string(); | ||
self.session.add_lint(lint, id, span, msg); | ||
} else { | ||
bug!("attempted to create unused macro error, but span not available"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
@@ -687,6 +707,8 @@ impl<'a> Resolver<'a> { | |
if attr::contains_name(&item.attrs, "macro_export") { | ||
let def = Def::Macro(def_id, MacroKind::Bang); | ||
self.macro_exports.push(Export { name: ident.name, def: def, span: item.span }); | ||
} else { | ||
self.unused_macros.insert(def_id, true); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -252,7 +252,11 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item) | |
valid: valid, | ||
}); | ||
|
||
NormalTT(exp, Some(def.span), attr::contains_name(&def.attrs, "allow_internal_unstable")) | ||
NormalTT( | ||
exp, | ||
Some((def.id, def.span)), | ||
attr::contains_name(&def.attrs, "allow_internal_unstable") | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: nonstandard formatting -- should be three lines with "visual indenting" or indented one block with four/five lines. |
||
} | ||
|
||
fn check_lhs_nt_follows(sess: &ParseSess, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we can't just remove the unused macro here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a FIXME below to get the remaining impls uncommented, including invocations of the macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense.