@@ -17,7 +17,7 @@ use rustc_session::lint::{
17
17
builtin:: { self , FORBIDDEN_LINT_GROUPS } ,
18
18
Level , Lint , LintExpectationId , LintId ,
19
19
} ;
20
- use rustc_session:: parse:: feature_err;
20
+ use rustc_session:: parse:: { add_feature_diagnostics , feature_err} ;
21
21
use rustc_session:: Session ;
22
22
use rustc_span:: symbol:: { sym, Symbol } ;
23
23
use rustc_span:: { source_map:: MultiSpan , Span , DUMMY_SP } ;
@@ -93,10 +93,19 @@ impl<'s> LintLevelsBuilder<'s> {
93
93
self . store
94
94
}
95
95
96
+ fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
97
+ & self . sets . list [ self . cur ] . specs
98
+ }
99
+
100
+ fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
101
+ & mut self . sets . list [ self . cur ] . specs
102
+ }
103
+
96
104
fn process_command_line ( & mut self , sess : & Session , store : & LintStore ) {
97
- let mut specs = FxHashMap :: default ( ) ;
98
105
self . sets . lint_cap = sess. opts . lint_cap . unwrap_or ( Level :: Forbid ) ;
99
106
107
+ self . cur =
108
+ self . sets . list . push ( LintSet { specs : FxHashMap :: default ( ) , parent : COMMAND_LINE } ) ;
100
109
for & ( ref lint_name, level) in & sess. opts . lint_opts {
101
110
store. check_lint_name_cmdline ( sess, & lint_name, level, self . registered_tools ) ;
102
111
let orig_level = level;
@@ -108,30 +117,24 @@ impl<'s> LintLevelsBuilder<'s> {
108
117
} ;
109
118
for id in ids {
110
119
// ForceWarn and Forbid cannot be overriden
111
- if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = specs . get ( & id) {
120
+ if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = self . current_specs ( ) . get ( & id) {
112
121
continue ;
113
122
}
114
123
115
- self . check_gated_lint ( id, DUMMY_SP ) ;
116
- let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
117
- specs. insert ( id, ( level, src) ) ;
124
+ if self . check_gated_lint ( id, DUMMY_SP ) {
125
+ let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
126
+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
127
+ }
118
128
}
119
129
}
120
-
121
- self . cur = self . sets . list . push ( LintSet { specs, parent : COMMAND_LINE } ) ;
122
130
}
123
131
124
132
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
125
133
/// (e.g. if a forbid was already inserted on the same scope), then emits a
126
134
/// diagnostic with no change to `specs`.
127
- fn insert_spec (
128
- & mut self ,
129
- specs : & mut FxHashMap < LintId , LevelAndSource > ,
130
- id : LintId ,
131
- ( level, src) : LevelAndSource ,
132
- ) {
135
+ fn insert_spec ( & mut self , id : LintId , ( level, src) : LevelAndSource ) {
133
136
let ( old_level, old_src) =
134
- self . sets . get_lint_level ( id. lint , self . cur , Some ( & specs ) , & self . sess ) ;
137
+ self . sets . get_lint_level ( id. lint , self . cur , Some ( self . current_specs ( ) ) , & self . sess ) ;
135
138
// Setting to a non-forbid level is an error if the lint previously had
136
139
// a forbid level. Note that this is not necessarily true even with a
137
140
// `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -154,7 +157,10 @@ impl<'s> LintLevelsBuilder<'s> {
154
157
} ;
155
158
debug ! (
156
159
"fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}" ,
157
- fcw_warning, specs, old_src, id_name
160
+ fcw_warning,
161
+ self . current_specs( ) ,
162
+ old_src,
163
+ id_name
158
164
) ;
159
165
160
166
let decorate_diag = |diag : & mut Diagnostic | {
@@ -213,9 +219,9 @@ impl<'s> LintLevelsBuilder<'s> {
213
219
}
214
220
}
215
221
if let Level :: ForceWarn = old_level {
216
- specs . insert ( id, ( old_level, old_src) ) ;
222
+ self . current_specs_mut ( ) . insert ( id, ( old_level, old_src) ) ;
217
223
} else {
218
- specs . insert ( id, ( level, src) ) ;
224
+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
219
225
}
220
226
}
221
227
@@ -239,7 +245,9 @@ impl<'s> LintLevelsBuilder<'s> {
239
245
is_crate_node : bool ,
240
246
source_hir_id : Option < HirId > ,
241
247
) -> BuilderPush {
242
- let mut specs = FxHashMap :: default ( ) ;
248
+ let prev = self . cur ;
249
+ self . cur = self . sets . list . push ( LintSet { specs : FxHashMap :: default ( ) , parent : prev } ) ;
250
+
243
251
let sess = self . sess ;
244
252
let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
245
253
for ( attr_index, attr) in attrs. iter ( ) . enumerate ( ) {
@@ -348,8 +356,9 @@ impl<'s> LintLevelsBuilder<'s> {
348
356
reason,
349
357
) ;
350
358
for & id in * ids {
351
- self . check_gated_lint ( id, attr. span ) ;
352
- self . insert_spec ( & mut specs, id, ( level, src) ) ;
359
+ if self . check_gated_lint ( id, attr. span ) {
360
+ self . insert_spec ( id, ( level, src) ) ;
361
+ }
353
362
}
354
363
if let Level :: Expect ( expect_id) = level {
355
364
self . lint_expectations
@@ -368,7 +377,7 @@ impl<'s> LintLevelsBuilder<'s> {
368
377
reason,
369
378
) ;
370
379
for id in ids {
371
- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
380
+ self . insert_spec ( * id, ( level, src) ) ;
372
381
}
373
382
if let Level :: Expect ( expect_id) = level {
374
383
self . lint_expectations
@@ -377,8 +386,12 @@ impl<'s> LintLevelsBuilder<'s> {
377
386
}
378
387
Err ( ( Some ( ids) , ref new_lint_name) ) => {
379
388
let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
380
- let ( lvl, src) =
381
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , & sess) ;
389
+ let ( lvl, src) = self . sets . get_lint_level (
390
+ lint,
391
+ self . cur ,
392
+ Some ( self . current_specs ( ) ) ,
393
+ & sess,
394
+ ) ;
382
395
struct_lint_level (
383
396
self . sess ,
384
397
lint,
@@ -408,7 +421,7 @@ impl<'s> LintLevelsBuilder<'s> {
408
421
reason,
409
422
) ;
410
423
for id in ids {
411
- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
424
+ self . insert_spec ( * id, ( level, src) ) ;
412
425
}
413
426
if let Level :: Expect ( expect_id) = level {
414
427
self . lint_expectations
@@ -448,8 +461,12 @@ impl<'s> LintLevelsBuilder<'s> {
448
461
449
462
CheckLintNameResult :: Warning ( msg, renamed) => {
450
463
let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
451
- let ( renamed_lint_level, src) =
452
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , & sess) ;
464
+ let ( renamed_lint_level, src) = self . sets . get_lint_level (
465
+ lint,
466
+ self . cur ,
467
+ Some ( self . current_specs ( ) ) ,
468
+ & sess,
469
+ ) ;
453
470
struct_lint_level (
454
471
self . sess ,
455
472
lint,
@@ -472,8 +489,12 @@ impl<'s> LintLevelsBuilder<'s> {
472
489
}
473
490
CheckLintNameResult :: NoLint ( suggestion) => {
474
491
let lint = builtin:: UNKNOWN_LINTS ;
475
- let ( level, src) =
476
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs) , self . sess ) ;
492
+ let ( level, src) = self . sets . get_lint_level (
493
+ lint,
494
+ self . cur ,
495
+ Some ( self . current_specs ( ) ) ,
496
+ self . sess ,
497
+ ) ;
477
498
struct_lint_level ( self . sess , lint, level, src, Some ( sp. into ( ) ) , |lint| {
478
499
let name = if let Some ( tool_ident) = tool_ident {
479
500
format ! ( "{}::{}" , tool_ident. name, name)
@@ -504,8 +525,9 @@ impl<'s> LintLevelsBuilder<'s> {
504
525
{
505
526
let src = LintLevelSource :: Node ( Symbol :: intern ( & new_name) , sp, reason) ;
506
527
for & id in ids {
507
- self . check_gated_lint ( id, attr. span ) ;
508
- self . insert_spec ( & mut specs, id, ( level, src) ) ;
528
+ if self . check_gated_lint ( id, attr. span ) {
529
+ self . insert_spec ( id, ( level, src) ) ;
530
+ }
509
531
}
510
532
if let Level :: Expect ( expect_id) = level {
511
533
self . lint_expectations
@@ -519,7 +541,7 @@ impl<'s> LintLevelsBuilder<'s> {
519
541
}
520
542
521
543
if !is_crate_node {
522
- for ( id, & ( level, ref src) ) in specs . iter ( ) {
544
+ for ( id, & ( level, ref src) ) in self . current_specs ( ) . iter ( ) {
523
545
if !id. lint . crate_level_only {
524
546
continue ;
525
547
}
@@ -530,7 +552,7 @@ impl<'s> LintLevelsBuilder<'s> {
530
552
531
553
let lint = builtin:: UNUSED_ATTRIBUTES ;
532
554
let ( lint_level, lint_src) =
533
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
555
+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
534
556
struct_lint_level (
535
557
self . sess ,
536
558
lint,
@@ -551,9 +573,9 @@ impl<'s> LintLevelsBuilder<'s> {
551
573
}
552
574
}
553
575
554
- let prev = self . cur ;
555
- if !specs . is_empty ( ) {
556
- self . cur = self . sets . list . push ( LintSet { specs , parent : prev } ) ;
576
+ if self . current_specs ( ) . is_empty ( ) {
577
+ self . sets . list . pop ( ) ;
578
+ self . cur = prev;
557
579
}
558
580
559
581
BuilderPush { prev, changed : prev != self . cur }
@@ -574,18 +596,24 @@ impl<'s> LintLevelsBuilder<'s> {
574
596
}
575
597
576
598
/// Checks if the lint is gated on a feature that is not enabled.
577
- fn check_gated_lint ( & self , lint_id : LintId , span : Span ) {
599
+ ///
600
+ /// Returns `true` if the lint's feature is enabled.
601
+ fn check_gated_lint ( & self , lint_id : LintId , span : Span ) -> bool {
578
602
if let Some ( feature) = lint_id. lint . feature_gate {
579
603
if !self . sess . features_untracked ( ) . enabled ( feature) {
580
- feature_err (
581
- & self . sess . parse_sess ,
582
- feature,
583
- span,
584
- & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) ) ,
585
- )
586
- . emit ( ) ;
604
+ let lint = builtin:: UNKNOWN_LINTS ;
605
+ let ( level, src) = self . lint_level ( builtin:: UNKNOWN_LINTS ) ;
606
+ struct_lint_level ( self . sess , lint, level, src, Some ( span. into ( ) ) , |lint_db| {
607
+ let mut db =
608
+ lint_db. build ( & format ! ( "unknown lint: `{}`" , lint_id. lint. name_lower( ) ) ) ;
609
+ db. note ( & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) , ) ) ;
610
+ add_feature_diagnostics ( & mut db, & self . sess . parse_sess , feature) ;
611
+ db. emit ( ) ;
612
+ } ) ;
613
+ return false ;
587
614
}
588
615
}
616
+ true
589
617
}
590
618
591
619
/// Called after `push` when the scope of a set of attributes are exited.
0 commit comments