Skip to content

Commit 05cd755

Browse files
committed
rustc_lint: Stop creating a fake ast::Crate for running early lints
Add a trait generalizing over the crate root and freshly loaded modules instead This also makes node IDs used for pre-expansion linting more precise
1 parent 9c70b6d commit 05cd755

File tree

5 files changed

+85
-26
lines changed

5 files changed

+85
-26
lines changed

compiler/rustc_expand/src/base.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -959,8 +959,9 @@ pub struct ExpansionData {
959959
pub is_trailing_mac: bool,
960960
}
961961

962-
type OnExternModLoaded<'a> =
963-
Option<&'a dyn Fn(Ident, Vec<Attribute>, Vec<P<Item>>, Span) -> (Vec<Attribute>, Vec<P<Item>>)>;
962+
type OnExternModLoaded<'a> = Option<
963+
&'a dyn Fn(NodeId, Vec<Attribute>, Vec<P<Item>>, Symbol) -> (Vec<Attribute>, Vec<P<Item>>),
964+
>;
964965

965966
/// One of these is made during expansion and incrementally updated as we go;
966967
/// when a macro expansion occurs, the resulting nodes have the `backtrace()

compiler/rustc_expand/src/expand.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,12 @@ impl InvocationCollectorNode for P<ast::Item> {
11081108
);
11091109

11101110
if let Some(extern_mod_loaded) = ecx.extern_mod_loaded {
1111-
(attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
1111+
(attrs, items) = extern_mod_loaded(
1112+
ecx.current_expansion.lint_node_id,
1113+
attrs,
1114+
items,
1115+
ident.name,
1116+
);
11121117
}
11131118

11141119
*mod_kind = ModKind::Loaded(items, Inline::No, inner_span);

compiler/rustc_interface/src/passes.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::proc_macro_decls;
33
use crate::util;
44

55
use rustc_ast::mut_visit::MutVisitor;
6-
use rustc_ast::{self as ast, visit, DUMMY_NODE_ID};
6+
use rustc_ast::{self as ast, visit};
77
use rustc_borrowck as mir_borrowck;
88
use rustc_codegen_ssa::back::link::emit_metadata;
99
use rustc_codegen_ssa::traits::CodegenBackend;
@@ -14,7 +14,7 @@ use rustc_errors::{Applicability, ErrorReported, PResult};
1414
use rustc_expand::base::{ExtCtxt, ResolverExpand};
1515
use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
1616
use rustc_hir::Crate;
17-
use rustc_lint::LintStore;
17+
use rustc_lint::{EarlyCheckNode, LintStore};
1818
use rustc_metadata::creader::CStore;
1919
use rustc_metadata::{encode_metadata, EncodedMetadata};
2020
use rustc_middle::arena::Arena;
@@ -34,7 +34,7 @@ use rustc_session::lint;
3434
use rustc_session::output::{filename_for_input, filename_for_metadata};
3535
use rustc_session::search_paths::PathKind;
3636
use rustc_session::{Limit, Session};
37-
use rustc_span::symbol::{sym, Ident, Symbol};
37+
use rustc_span::symbol::{sym, Symbol};
3838
use rustc_span::{FileName, MultiSpan};
3939
use rustc_trait_selection::traits;
4040
use rustc_typeck as typeck;
@@ -233,11 +233,11 @@ pub fn register_plugins<'a>(
233233
Ok((krate, lint_store))
234234
}
235235

236-
fn pre_expansion_lint(
236+
fn pre_expansion_lint<'a>(
237237
sess: &Session,
238238
lint_store: &LintStore,
239239
registered_tools: &RegisteredTools,
240-
check_node: &ast::Crate,
240+
check_node: impl EarlyCheckNode<'a>,
241241
node_name: &str,
242242
) {
243243
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
@@ -322,10 +322,15 @@ pub fn configure_and_expand(
322322
};
323323

324324
let registered_tools = resolver.registered_tools().clone();
325-
let extern_mod_loaded = |ident: Ident, attrs, items, span| {
326-
let krate = ast::Crate { attrs, items, span, id: DUMMY_NODE_ID, is_placeholder: false };
327-
pre_expansion_lint(sess, lint_store, &registered_tools, &krate, ident.name.as_str());
328-
(krate.attrs, krate.items)
325+
let extern_mod_loaded = |node_id, attrs: Vec<_>, items: Vec<_>, name: Symbol| {
326+
pre_expansion_lint(
327+
sess,
328+
lint_store,
329+
&registered_tools,
330+
(node_id, &*attrs, &*items),
331+
name.as_str(),
332+
);
333+
(attrs, items)
329334
};
330335
let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded));
331336

@@ -507,7 +512,7 @@ pub fn lower_to_hir<'res, 'tcx>(
507512
resolver.registered_tools(),
508513
lint_buffer,
509514
rustc_lint::BuiltinCombinedEarlyLintPass::new(),
510-
&krate,
515+
&*krate,
511516
)
512517
});
513518

compiler/rustc_lint/src/early.rs

+60-12
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
1717
use crate::context::{EarlyContext, LintContext, LintStore};
1818
use crate::passes::{EarlyLintPass, EarlyLintPassObject};
19-
use rustc_ast as ast;
20-
use rustc_ast::visit as ast_visit;
19+
use rustc_ast::ptr::P;
20+
use rustc_ast::visit::{self as ast_visit, Visitor};
2121
use rustc_ast::AstLike;
22+
use rustc_ast::{self as ast, walk_list};
2223
use rustc_middle::ty::RegisteredTools;
2324
use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
2425
use rustc_session::Session;
@@ -32,7 +33,7 @@ macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
3233
$cx.pass.$f(&$cx.context, $($args),*);
3334
}) }
3435

35-
struct EarlyContextAndPass<'a, T: EarlyLintPass> {
36+
pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
3637
context: EarlyContext<'a>,
3738
pass: T,
3839
}
@@ -326,14 +327,65 @@ macro_rules! early_lint_pass_impl {
326327

327328
crate::early_lint_methods!(early_lint_pass_impl, []);
328329

329-
fn early_lint_node(
330+
/// Early lints work on different nodes - either on the crate root, or on freshly loaded modules.
331+
/// This trait generalizes over those nodes.
332+
pub trait EarlyCheckNode<'a>: Copy {
333+
fn id(self) -> ast::NodeId;
334+
fn attrs<'b>(self) -> &'b [ast::Attribute]
335+
where
336+
'a: 'b;
337+
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
338+
where
339+
'a: 'b;
340+
}
341+
342+
impl<'a> EarlyCheckNode<'a> for &'a ast::Crate {
343+
fn id(self) -> ast::NodeId {
344+
ast::CRATE_NODE_ID
345+
}
346+
fn attrs<'b>(self) -> &'b [ast::Attribute]
347+
where
348+
'a: 'b,
349+
{
350+
&self.attrs
351+
}
352+
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
353+
where
354+
'a: 'b,
355+
{
356+
run_early_pass!(cx, check_crate, self);
357+
ast_visit::walk_crate(cx, self);
358+
run_early_pass!(cx, check_crate_post, self);
359+
}
360+
}
361+
362+
impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::Item>]) {
363+
fn id(self) -> ast::NodeId {
364+
self.0
365+
}
366+
fn attrs<'b>(self) -> &'b [ast::Attribute]
367+
where
368+
'a: 'b,
369+
{
370+
self.1
371+
}
372+
fn check<'b>(self, cx: &mut EarlyContextAndPass<'b, impl EarlyLintPass>)
373+
where
374+
'a: 'b,
375+
{
376+
walk_list!(cx, visit_attribute, self.1);
377+
walk_list!(cx, visit_item, self.2);
378+
}
379+
}
380+
381+
fn early_lint_node<'a>(
330382
sess: &Session,
331383
warn_about_weird_lints: bool,
332384
lint_store: &LintStore,
333385
registered_tools: &RegisteredTools,
334386
buffered: LintBuffer,
335387
pass: impl EarlyLintPass,
336-
check_node: &ast::Crate,
388+
check_node: impl EarlyCheckNode<'a>,
337389
) -> LintBuffer {
338390
let mut cx = EarlyContextAndPass {
339391
context: EarlyContext::new(
@@ -346,22 +398,18 @@ fn early_lint_node(
346398
pass,
347399
};
348400

349-
cx.with_lint_attrs(ast::CRATE_NODE_ID, &check_node.attrs, |cx| {
350-
run_early_pass!(cx, check_crate, check_node);
351-
ast_visit::walk_crate(cx, check_node);
352-
run_early_pass!(cx, check_crate_post, check_node);
353-
});
401+
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
354402
cx.context.buffered
355403
}
356404

357-
pub fn check_ast_node(
405+
pub fn check_ast_node<'a>(
358406
sess: &Session,
359407
pre_expansion: bool,
360408
lint_store: &LintStore,
361409
registered_tools: &RegisteredTools,
362410
lint_buffer: Option<LintBuffer>,
363411
builtin_lints: impl EarlyLintPass,
364-
check_node: &ast::Crate,
412+
check_node: impl EarlyCheckNode<'a>,
365413
) {
366414
let passes =
367415
if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };

compiler/rustc_lint/src/levels.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust;
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
77
use rustc_hir as hir;
8-
use rustc_hir::{intravisit, HirId, CRATE_HIR_ID};
8+
use rustc_hir::{intravisit, HirId};
99
use rustc_middle::hir::nested_filter;
1010
use rustc_middle::lint::LevelAndSource;
1111
use rustc_middle::lint::LintDiagnosticBuilder;

0 commit comments

Comments
 (0)