@@ -93,10 +93,21 @@ 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 = self . sets . list . push ( LintSet {
108
+ specs : FxHashMap :: default ( ) ,
109
+ parent : COMMAND_LINE ,
110
+ } ) ;
100
111
for & ( ref lint_name, level) in & sess. opts . lint_opts {
101
112
store. check_lint_name_cmdline ( sess, & lint_name, level, self . registered_tools ) ;
102
113
let orig_level = level;
@@ -108,30 +119,28 @@ impl<'s> LintLevelsBuilder<'s> {
108
119
} ;
109
120
for id in ids {
110
121
// ForceWarn and Forbid cannot be overriden
111
- if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = specs . get ( & id) {
122
+ if let Some ( ( Level :: ForceWarn | Level :: Forbid , _) ) = self . current_specs ( ) . get ( & id) {
112
123
continue ;
113
124
}
114
125
115
- self . check_gated_lint ( id, DUMMY_SP ) ;
116
- let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
117
- specs. insert ( id, ( level, src) ) ;
126
+ if self . check_gated_lint ( id, DUMMY_SP ) {
127
+ let src = LintLevelSource :: CommandLine ( lint_flag_val, orig_level) ;
128
+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
129
+ }
118
130
}
119
131
}
120
-
121
- self . cur = self . sets . list . push ( LintSet { specs, parent : COMMAND_LINE } ) ;
122
132
}
123
133
124
134
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
125
135
/// (e.g. if a forbid was already inserted on the same scope), then emits a
126
136
/// diagnostic with no change to `specs`.
127
137
fn insert_spec (
128
138
& mut self ,
129
- specs : & mut FxHashMap < LintId , LevelAndSource > ,
130
139
id : LintId ,
131
140
( level, src) : LevelAndSource ,
132
141
) {
133
142
let ( old_level, old_src) =
134
- self . sets . get_lint_level ( id. lint , self . cur , Some ( & specs ) , & self . sess ) ;
143
+ self . sets . get_lint_level ( id. lint , self . cur , Some ( self . current_specs ( ) ) , & self . sess ) ;
135
144
// Setting to a non-forbid level is an error if the lint previously had
136
145
// a forbid level. Note that this is not necessarily true even with a
137
146
// `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
@@ -154,7 +163,7 @@ impl<'s> LintLevelsBuilder<'s> {
154
163
} ;
155
164
debug ! (
156
165
"fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}" ,
157
- fcw_warning, specs , old_src, id_name
166
+ fcw_warning, self . current_specs ( ) , old_src, id_name
158
167
) ;
159
168
160
169
let decorate_diag = |diag : & mut Diagnostic | {
@@ -213,9 +222,9 @@ impl<'s> LintLevelsBuilder<'s> {
213
222
}
214
223
}
215
224
if let Level :: ForceWarn = old_level {
216
- specs . insert ( id, ( old_level, old_src) ) ;
225
+ self . current_specs_mut ( ) . insert ( id, ( old_level, old_src) ) ;
217
226
} else {
218
- specs . insert ( id, ( level, src) ) ;
227
+ self . current_specs_mut ( ) . insert ( id, ( level, src) ) ;
219
228
}
220
229
}
221
230
@@ -239,7 +248,11 @@ impl<'s> LintLevelsBuilder<'s> {
239
248
is_crate_node : bool ,
240
249
source_hir_id : Option < HirId > ,
241
250
) -> BuilderPush {
242
- let mut specs = FxHashMap :: default ( ) ;
251
+ let prev = self . cur ;
252
+ self . cur = self . sets . list . push ( LintSet {
253
+ specs : FxHashMap :: default ( ) ,
254
+ parent : prev,
255
+ } ) ;
243
256
let sess = self . sess ;
244
257
let bad_attr = |span| struct_span_err ! ( sess, span, E0452 , "malformed lint attribute input" ) ;
245
258
for ( attr_index, attr) in attrs. iter ( ) . enumerate ( ) {
@@ -348,8 +361,9 @@ impl<'s> LintLevelsBuilder<'s> {
348
361
reason,
349
362
) ;
350
363
for & id in * ids {
351
- self . check_gated_lint ( id, attr. span ) ;
352
- self . insert_spec ( & mut specs, id, ( level, src) ) ;
364
+ if self . check_gated_lint ( id, attr. span ) {
365
+ self . insert_spec ( id, ( level, src) ) ;
366
+ }
353
367
}
354
368
if let Level :: Expect ( expect_id) = level {
355
369
self . lint_expectations
@@ -368,7 +382,7 @@ impl<'s> LintLevelsBuilder<'s> {
368
382
reason,
369
383
) ;
370
384
for id in ids {
371
- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
385
+ self . insert_spec ( * id, ( level, src) ) ;
372
386
}
373
387
if let Level :: Expect ( expect_id) = level {
374
388
self . lint_expectations
@@ -378,7 +392,7 @@ impl<'s> LintLevelsBuilder<'s> {
378
392
Err ( ( Some ( ids) , ref new_lint_name) ) => {
379
393
let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
380
394
let ( lvl, src) =
381
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , & sess) ;
395
+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , & sess) ;
382
396
struct_lint_level (
383
397
self . sess ,
384
398
lint,
@@ -408,7 +422,7 @@ impl<'s> LintLevelsBuilder<'s> {
408
422
reason,
409
423
) ;
410
424
for id in ids {
411
- self . insert_spec ( & mut specs , * id, ( level, src) ) ;
425
+ self . insert_spec ( * id, ( level, src) ) ;
412
426
}
413
427
if let Level :: Expect ( expect_id) = level {
414
428
self . lint_expectations
@@ -449,7 +463,7 @@ impl<'s> LintLevelsBuilder<'s> {
449
463
CheckLintNameResult :: Warning ( msg, renamed) => {
450
464
let lint = builtin:: RENAMED_AND_REMOVED_LINTS ;
451
465
let ( renamed_lint_level, src) =
452
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , & sess) ;
466
+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , & sess) ;
453
467
struct_lint_level (
454
468
self . sess ,
455
469
lint,
@@ -473,7 +487,7 @@ impl<'s> LintLevelsBuilder<'s> {
473
487
CheckLintNameResult :: NoLint ( suggestion) => {
474
488
let lint = builtin:: UNKNOWN_LINTS ;
475
489
let ( level, src) =
476
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
490
+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
477
491
struct_lint_level ( self . sess , lint, level, src, Some ( sp. into ( ) ) , |lint| {
478
492
let name = if let Some ( tool_ident) = tool_ident {
479
493
format ! ( "{}::{}" , tool_ident. name, name)
@@ -504,8 +518,9 @@ impl<'s> LintLevelsBuilder<'s> {
504
518
{
505
519
let src = LintLevelSource :: Node ( Symbol :: intern ( & new_name) , sp, reason) ;
506
520
for & id in ids {
507
- self . check_gated_lint ( id, attr. span ) ;
508
- self . insert_spec ( & mut specs, id, ( level, src) ) ;
521
+ if self . check_gated_lint ( id, attr. span ) {
522
+ self . insert_spec ( id, ( level, src) ) ;
523
+ }
509
524
}
510
525
if let Level :: Expect ( expect_id) = level {
511
526
self . lint_expectations
@@ -519,7 +534,7 @@ impl<'s> LintLevelsBuilder<'s> {
519
534
}
520
535
521
536
if !is_crate_node {
522
- for ( id, & ( level, ref src) ) in specs . iter ( ) {
537
+ for ( id, & ( level, ref src) ) in self . current_specs ( ) . iter ( ) {
523
538
if !id. lint . crate_level_only {
524
539
continue ;
525
540
}
@@ -530,7 +545,7 @@ impl<'s> LintLevelsBuilder<'s> {
530
545
531
546
let lint = builtin:: UNUSED_ATTRIBUTES ;
532
547
let ( lint_level, lint_src) =
533
- self . sets . get_lint_level ( lint, self . cur , Some ( & specs ) , self . sess ) ;
548
+ self . sets . get_lint_level ( lint, self . cur , Some ( self . current_specs ( ) ) , self . sess ) ;
534
549
struct_lint_level (
535
550
self . sess ,
536
551
lint,
@@ -551,9 +566,9 @@ impl<'s> LintLevelsBuilder<'s> {
551
566
}
552
567
}
553
568
554
- let prev = self . cur ;
555
- if !specs . is_empty ( ) {
556
- self . cur = self . sets . list . push ( LintSet { specs , parent : prev } ) ;
569
+ if self . current_specs ( ) . is_empty ( ) {
570
+ self . sets . list . pop ( ) ;
571
+ self . cur = prev;
557
572
}
558
573
559
574
BuilderPush { prev, changed : prev != self . cur }
@@ -574,18 +589,25 @@ impl<'s> LintLevelsBuilder<'s> {
574
589
}
575
590
576
591
/// Checks if the lint is gated on a feature that is not enabled.
577
- fn check_gated_lint ( & self , lint_id : LintId , span : Span ) {
592
+ ///
593
+ /// Returns `true` if the lint's feature is enabled.
594
+ fn check_gated_lint ( & self , lint_id : LintId , span : Span ) -> bool {
578
595
if let Some ( feature) = lint_id. lint . feature_gate {
579
596
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 ( ) ;
597
+ let ( unknown_lints_level, _) = self . lint_level ( builtin:: UNKNOWN_LINTS ) ;
598
+ if unknown_lints_level != Level :: Allow {
599
+ feature_err (
600
+ & self . sess . parse_sess ,
601
+ feature,
602
+ span,
603
+ & format ! ( "the `{}` lint is unstable" , lint_id. lint. name_lower( ) ) ,
604
+ )
605
+ . emit ( ) ;
606
+ }
607
+ return false ;
587
608
}
588
609
}
610
+ true
589
611
}
590
612
591
613
/// Called after `push` when the scope of a set of attributes are exited.
0 commit comments