@@ -8,36 +8,73 @@ use rustc_ast::ptr::P;
88use rustc_ast:: visit:: { self as ast_visit, Visitor , walk_list} ;
99use rustc_ast:: { self as ast, HasAttrs } ;
1010use rustc_data_structures:: stack:: ensure_sufficient_stack;
11+ use rustc_errors:: MultiSpan ;
1112use rustc_feature:: Features ;
12- use rustc_middle:: ty:: RegisteredTools ;
13+ use rustc_middle:: ty:: { RegisteredTools , TyCtxt } ;
1314use rustc_session:: Session ;
14- use rustc_session:: lint:: { BufferedEarlyLint , LintBuffer , LintPass } ;
15+ use rustc_session:: lint:: { BufferedEarlyLint , BuiltinLintDiag , LintBuffer , LintPass } ;
1516use rustc_span:: Span ;
1617use rustc_span:: symbol:: Ident ;
1718use tracing:: debug;
1819
19- use crate :: context:: { EarlyContext , LintStore } ;
20+ use crate :: Lint ;
21+ use crate :: context:: { EarlyContext , LintContext , LintStore } ;
2022use crate :: passes:: { EarlyLintPass , EarlyLintPassObject } ;
2123
24+ mod diagnostics;
25+
2226macro_rules! lint_callback { ( $cx: expr, $f: ident, $( $args: expr) ,* ) => ( {
2327 $cx. pass. $f( & $cx. context, $( $args) ,* ) ;
2428} ) }
2529
2630/// Implements the AST traversal for early lint passes. `T` provides the
2731/// `check_*` methods.
28- pub struct EarlyContextAndPass < ' a , T : EarlyLintPass > {
32+ pub struct EarlyContextAndPass < ' a , ' b , T : EarlyLintPass > {
2933 context : EarlyContext < ' a > ,
34+ tcx : Option < TyCtxt < ' b > > ,
3035 pass : T ,
3136}
3237
33- impl < ' a , T : EarlyLintPass > EarlyContextAndPass < ' a , T > {
38+ impl < T : EarlyLintPass > EarlyContextAndPass < ' _ , ' _ , T > {
39+ /// Emit a lint at the appropriate level, with an associated span and an existing
40+ /// diagnostic.
41+ ///
42+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
43+ #[ rustc_lint_diagnostics]
44+ pub fn span_lint_with_diagnostics (
45+ & self ,
46+ lint : & ' static Lint ,
47+ span : MultiSpan ,
48+ diagnostic : BuiltinLintDiag ,
49+ ) {
50+ self . opt_span_lint_with_diagnostics ( lint, Some ( span) , diagnostic) ;
51+ }
52+
53+ /// Emit a lint at the appropriate level, with an optional associated span and an existing
54+ /// diagnostic.
55+ ///
56+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
57+ #[ rustc_lint_diagnostics]
58+ pub fn opt_span_lint_with_diagnostics (
59+ & self ,
60+ lint : & ' static Lint ,
61+ span : Option < MultiSpan > ,
62+ diagnostic : BuiltinLintDiag ,
63+ ) {
64+ self . context . opt_span_lint ( lint, span, |diag| {
65+ diagnostics:: decorate_lint ( self . context . sess ( ) , self . tcx , diagnostic, diag) ;
66+ } ) ;
67+ }
68+ }
69+
70+ impl < ' a , ' b , T : EarlyLintPass > EarlyContextAndPass < ' a , ' b , T > {
3471 // This always-inlined function is for the hot call site.
3572 #[ inline( always) ]
3673 #[ allow( rustc:: diagnostic_outside_of_impl) ]
3774 fn inlined_check_id ( & mut self , id : ast:: NodeId ) {
3875 for early_lint in self . context . buffered . take ( id) {
3976 let BufferedEarlyLint { span, node_id : _, lint_id, diagnostic } = early_lint;
40- self . context . opt_span_lint_with_diagnostics ( lint_id. lint , span, diagnostic) ;
77+ self . opt_span_lint_with_diagnostics ( lint_id. lint , span, diagnostic) ;
4178 }
4279 }
4380
@@ -67,7 +104,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
67104 }
68105}
69106
70- impl < ' a , T : EarlyLintPass > ast_visit:: Visitor < ' a > for EarlyContextAndPass < ' a , T > {
107+ impl < ' a , ' b , T : EarlyLintPass > ast_visit:: Visitor < ' a > for EarlyContextAndPass < ' a , ' b , T > {
71108 fn visit_coroutine_kind ( & mut self , coroutine_kind : & ' a ast:: CoroutineKind ) -> Self :: Result {
72109 self . check_id ( coroutine_kind. closure_id ( ) ) ;
73110 }
@@ -313,7 +350,7 @@ pub trait EarlyCheckNode<'a>: Copy {
313350 fn attrs < ' b > ( self ) -> & ' b [ ast:: Attribute ]
314351 where
315352 ' a : ' b ;
316- fn check < ' b , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , T > )
353+ fn check < ' b , ' c , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , ' c , T > )
317354 where
318355 ' a : ' b ;
319356}
@@ -328,7 +365,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) {
328365 {
329366 self . 1
330367 }
331- fn check < ' b , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , T > )
368+ fn check < ' b , ' c , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , ' c , T > )
332369 where
333370 ' a : ' b ,
334371 {
@@ -348,7 +385,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
348385 {
349386 self . 1
350387 }
351- fn check < ' b , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , T > )
388+ fn check < ' b , ' c , T : EarlyLintPass > ( self , cx : & mut EarlyContextAndPass < ' b , ' c , T > )
352389 where
353390 ' a : ' b ,
354391 {
@@ -359,6 +396,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
359396
360397pub fn check_ast_node < ' a > (
361398 sess : & Session ,
399+ tcx : Option < TyCtxt < ' _ > > ,
362400 features : & Features ,
363401 pre_expansion : bool ,
364402 lint_store : & LintStore ,
@@ -382,22 +420,23 @@ pub fn check_ast_node<'a>(
382420 let passes =
383421 if pre_expansion { & lint_store. pre_expansion_passes } else { & lint_store. early_passes } ;
384422 if passes. is_empty ( ) {
385- check_ast_node_inner ( sess, check_node, context, builtin_lints) ;
423+ check_ast_node_inner ( sess, tcx , check_node, context, builtin_lints) ;
386424 } else {
387425 let mut passes: Vec < _ > = passes. iter ( ) . map ( |mk_pass| ( mk_pass) ( ) ) . collect ( ) ;
388426 passes. push ( Box :: new ( builtin_lints) ) ;
389427 let pass = RuntimeCombinedEarlyLintPass { passes : & mut passes[ ..] } ;
390- check_ast_node_inner ( sess, check_node, context, pass) ;
428+ check_ast_node_inner ( sess, tcx , check_node, context, pass) ;
391429 }
392430}
393431
394432fn check_ast_node_inner < ' a , T : EarlyLintPass > (
395433 sess : & Session ,
434+ tcx : Option < TyCtxt < ' _ > > ,
396435 check_node : impl EarlyCheckNode < ' a > ,
397436 context : EarlyContext < ' _ > ,
398437 pass : T ,
399438) {
400- let mut cx = EarlyContextAndPass { context, pass } ;
439+ let mut cx = EarlyContextAndPass { context, tcx , pass } ;
401440
402441 cx. with_lint_attrs ( check_node. id ( ) , check_node. attrs ( ) , |cx| check_node. check ( cx) ) ;
403442
0 commit comments