diff options
Diffstat (limited to 'compiler/rustc_lint/src/early.rs')
| -rw-r--r-- | compiler/rustc_lint/src/early.rs | 127 |
1 files changed, 85 insertions, 42 deletions
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0bba66d3838..1b2c88867d4 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -16,9 +16,11 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; -use rustc_ast as ast; -use rustc_ast::visit as ast_visit; +use rustc_ast::ptr::P; +use rustc_ast::visit::{self as ast_visit, Visitor}; use rustc_ast::AstLike; +use rustc_ast::{self as ast, walk_list}; +use rustc_middle::ty::RegisteredTools; use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_session::Session; use rustc_span::symbol::Ident; @@ -31,7 +33,7 @@ macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -struct EarlyContextAndPass<'a, T: EarlyLintPass> { +pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { context: EarlyContext<'a>, pass: T, } @@ -57,7 +59,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { F: FnOnce(&mut Self), { let is_crate_node = id == ast::CRATE_NODE_ID; - let push = self.context.builder.push(attrs, &self.context.lint_store, is_crate_node); + let push = self.context.builder.push(attrs, is_crate_node); self.check_id(id); self.enter_attrs(attrs); f(self); @@ -325,48 +327,89 @@ macro_rules! early_lint_pass_impl { crate::early_lint_methods!(early_lint_pass_impl, []); -fn early_lint_crate<T: EarlyLintPass>( +/// Early lints work on different nodes - either on the crate root, or on freshly loaded modules. +/// This trait generalizes over those nodes. +pub trait EarlyCheckNode<'a>: Copy { + fn id(self) -> ast::NodeId; + fn attrs<'b>(self) -> &'b [ast::Attribute] + where + 'a: 'b; + fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + where + 'a: 'b; +} + +impl<'a> EarlyCheckNode<'a> for &'a ast::Crate { + fn id(self) -> ast::NodeId { + ast::CRATE_NODE_ID + } + fn attrs<'b>(self) -> &'b [ast::Attribute] + where + 'a: 'b, + { + &self.attrs + } + fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + where + 'a: 'b, + { + run_early_pass!(cx, check_crate, self); + ast_visit::walk_crate(cx, self); + run_early_pass!(cx, check_crate_post, self); + } +} + +impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::Item>]) { + fn id(self) -> ast::NodeId { + self.0 + } + fn attrs<'b>(self) -> &'b [ast::Attribute] + where + 'a: 'b, + { + self.1 + } + fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>) + where + 'a: 'b, + { + walk_list!(cx, visit_attribute, self.1); + walk_list!(cx, visit_item, self.2); + } +} + +fn early_lint_node<'a>( sess: &Session, + warn_about_weird_lints: bool, lint_store: &LintStore, - krate: &ast::Crate, - crate_attrs: &[ast::Attribute], - pass: T, + registered_tools: &RegisteredTools, buffered: LintBuffer, - warn_about_weird_lints: bool, + pass: impl EarlyLintPass, + check_node: impl EarlyCheckNode<'a>, ) -> LintBuffer { let mut cx = EarlyContextAndPass { context: EarlyContext::new( sess, + warn_about_weird_lints, lint_store, - krate, - crate_attrs, + registered_tools, buffered, - warn_about_weird_lints, ), pass, }; - // Visit the whole crate. - cx.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |cx| { - // since the root module isn't visited as an item (because it isn't an - // item), warn for it here. - run_early_pass!(cx, check_crate, krate); - - ast_visit::walk_crate(cx, krate); - - run_early_pass!(cx, check_crate_post, krate); - }); + cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); cx.context.buffered } -pub fn check_ast_crate<T: EarlyLintPass>( +pub fn check_ast_node<'a>( sess: &Session, - lint_store: &LintStore, - krate: &ast::Crate, - crate_attrs: &[ast::Attribute], pre_expansion: bool, + lint_store: &LintStore, + registered_tools: &RegisteredTools, lint_buffer: Option<LintBuffer>, - builtin_lints: T, + builtin_lints: impl EarlyLintPass, + check_node: impl EarlyCheckNode<'a>, ) { let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; @@ -374,39 +417,39 @@ pub fn check_ast_crate<T: EarlyLintPass>( let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { - buffered = early_lint_crate( + buffered = early_lint_node( sess, + pre_expansion, lint_store, - krate, - crate_attrs, - builtin_lints, + registered_tools, buffered, - pre_expansion, + builtin_lints, + check_node, ); if !passes.is_empty() { - buffered = early_lint_crate( + buffered = early_lint_node( sess, + false, lint_store, - krate, - crate_attrs, - EarlyLintPassObjects { lints: &mut passes[..] }, + registered_tools, buffered, - false, + EarlyLintPassObjects { lints: &mut passes[..] }, + check_node, ); } } else { for (i, pass) in passes.iter_mut().enumerate() { buffered = sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| { - early_lint_crate( + early_lint_node( sess, + pre_expansion && i == 0, lint_store, - krate, - crate_attrs, - EarlyLintPassObjects { lints: slice::from_mut(pass) }, + registered_tools, buffered, - pre_expansion && i == 0, + EarlyLintPassObjects { lints: slice::from_mut(pass) }, + check_node, ) }); } |
