@@ -8,36 +8,73 @@ use rustc_ast::ptr::P;
8
8
use rustc_ast:: visit:: { self as ast_visit, Visitor , walk_list} ;
9
9
use rustc_ast:: { self as ast, HasAttrs } ;
10
10
use rustc_data_structures:: stack:: ensure_sufficient_stack;
11
+ use rustc_errors:: MultiSpan ;
11
12
use rustc_feature:: Features ;
12
- use rustc_middle:: ty:: RegisteredTools ;
13
+ use rustc_middle:: ty:: { RegisteredTools , TyCtxt } ;
13
14
use rustc_session:: Session ;
14
- use rustc_session:: lint:: { BufferedEarlyLint , LintBuffer , LintPass } ;
15
+ use rustc_session:: lint:: { BufferedEarlyLint , BuiltinLintDiag , LintBuffer , LintPass } ;
15
16
use rustc_span:: Span ;
16
17
use rustc_span:: symbol:: Ident ;
17
18
use tracing:: debug;
18
19
19
- use crate :: context:: { EarlyContext , LintStore } ;
20
+ use crate :: Lint ;
21
+ use crate :: context:: { EarlyContext , LintContext , LintStore } ;
20
22
use crate :: passes:: { EarlyLintPass , EarlyLintPassObject } ;
21
23
24
+ mod diagnostics;
25
+
22
26
macro_rules! lint_callback { ( $cx: expr, $f: ident, $( $args: expr) ,* ) => ( {
23
27
$cx. pass. $f( & $cx. context, $( $args) ,* ) ;
24
28
} ) }
25
29
26
30
/// Implements the AST traversal for early lint passes. `T` provides the
27
31
/// `check_*` methods.
28
- pub struct EarlyContextAndPass < ' a , T : EarlyLintPass > {
32
+ pub struct EarlyContextAndPass < ' a , ' b , T : EarlyLintPass > {
29
33
context : EarlyContext < ' a > ,
34
+ tcx : Option < TyCtxt < ' b > > ,
30
35
pass : T ,
31
36
}
32
37
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 > {
34
71
// This always-inlined function is for the hot call site.
35
72
#[ inline( always) ]
36
73
#[ allow( rustc:: diagnostic_outside_of_impl) ]
37
74
fn inlined_check_id ( & mut self , id : ast:: NodeId ) {
38
75
for early_lint in self . context . buffered . take ( id) {
39
76
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) ;
41
78
}
42
79
}
43
80
@@ -67,7 +104,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
67
104
}
68
105
}
69
106
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 > {
71
108
fn visit_coroutine_kind ( & mut self , coroutine_kind : & ' a ast:: CoroutineKind ) -> Self :: Result {
72
109
self . check_id ( coroutine_kind. closure_id ( ) ) ;
73
110
}
@@ -313,7 +350,7 @@ pub trait EarlyCheckNode<'a>: Copy {
313
350
fn attrs < ' b > ( self ) -> & ' b [ ast:: Attribute ]
314
351
where
315
352
' 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 > )
317
354
where
318
355
' a : ' b ;
319
356
}
@@ -328,7 +365,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) {
328
365
{
329
366
self . 1
330
367
}
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 > )
332
369
where
333
370
' a : ' b ,
334
371
{
@@ -348,7 +385,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
348
385
{
349
386
self . 1
350
387
}
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 > )
352
389
where
353
390
' a : ' b ,
354
391
{
@@ -359,6 +396,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
359
396
360
397
pub fn check_ast_node < ' a > (
361
398
sess : & Session ,
399
+ tcx : Option < TyCtxt < ' _ > > ,
362
400
features : & Features ,
363
401
pre_expansion : bool ,
364
402
lint_store : & LintStore ,
@@ -382,22 +420,23 @@ pub fn check_ast_node<'a>(
382
420
let passes =
383
421
if pre_expansion { & lint_store. pre_expansion_passes } else { & lint_store. early_passes } ;
384
422
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) ;
386
424
} else {
387
425
let mut passes: Vec < _ > = passes. iter ( ) . map ( |mk_pass| ( mk_pass) ( ) ) . collect ( ) ;
388
426
passes. push ( Box :: new ( builtin_lints) ) ;
389
427
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) ;
391
429
}
392
430
}
393
431
394
432
fn check_ast_node_inner < ' a , T : EarlyLintPass > (
395
433
sess : & Session ,
434
+ tcx : Option < TyCtxt < ' _ > > ,
396
435
check_node : impl EarlyCheckNode < ' a > ,
397
436
context : EarlyContext < ' _ > ,
398
437
pass : T ,
399
438
) {
400
- let mut cx = EarlyContextAndPass { context, pass } ;
439
+ let mut cx = EarlyContextAndPass { context, tcx , pass } ;
401
440
402
441
cx. with_lint_attrs ( check_node. id ( ) , check_node. attrs ( ) , |cx| check_node. check ( cx) ) ;
403
442
0 commit comments