1616
1717use crate :: context:: { EarlyContext , LintContext , LintStore } ;
1818use 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 } ;
2121use rustc_ast:: AstLike ;
22+ use rustc_ast:: { self as ast, walk_list} ;
2223use rustc_middle:: ty:: RegisteredTools ;
2324use rustc_session:: lint:: { BufferedEarlyLint , LintBuffer , LintPass } ;
2425use 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
327328crate :: 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 } ;
0 commit comments